PROGRAM KONTROL DEYİMLERİ

 8.1.1. IF Yapısı

 Programın akışını IF değimi ile birlikte verilen koşula bağlı olarak belirlenen veya ELSE, ELSEIF veya END IF değimleri ile oluşturulan  işlem bloğuna geçmesini veya söz konusu program bloğunun işletilmeyip atlatılmasını sağlar.

 Yazılım :

 

                        IF Şart THEN

                                   Komutlar

                        ELSE

                                   Komutlar

                        END IF

 

Şartın gerçekleşmesi durumunda THEN değiminden sonraki satır işletilir. Gerçekleşmemesi durumunda ise ELSE değiminden sonraki satırlar işletilir.           

Tek satırda şart yazılırsa  END IF değimi kullanılmaz.

                       IF Şart Komutlar THEN Komutlar

            IF Şart Komutlar

 

Örnek 8.1  :   Girilen üç notun ortalamasını alıp, bu notların ortalamasına göre öğrencinin geçip veya kaldığını yazan programı yapınız?

 

Private Sub Form_Load()

 

Dim n1,n2,n3,ort

  n1=val(InputBox(“1.Sınav Notunu Giriniz:”, “Sınav”);

  n2=val(InputBox(“2.Sınav Notunu Giriniz:”, “Sınav”);

  n3=val(InputBox(“3.Sınav Notunu Giriniz:”, “Sınav”);

  ort=(n1+n2+n3)/3

             IF (ort<50) Then

     MsgBox(“Kaldınız” &ort)

 

 Else

 

    MsgBox(“Geçtiniz” &ort)

 END IF

End Sub

 

8.1.2. Select Case Yapısı   

İşlev bakımından IF değimine çok benzemektedir. Çok sayıda IF yapısı içi içe kullanıldığı zaman programın okunurluğu azalır ve programı izlemek zorlaşır. Bu gibi durumlarda Select Case yapısı kullanılır.

 Yazılım : 

            Select Case Kontrol Değişkeni

                        Case ifade 1

                                   ……

                        Case ifade 2

                                   …….

                        Case Else

                                   …….

            End Select

 Genel yazılımdan anlaşılacağı gibi bloğu başlatan Select Case değiminden sonra yapılacak karşılaştırmalarda kullanılacak bir kontrol değişkeni bulunmaktadır. Eğer kontrol değişkeninin içeriği “ifade1” olarak verilen değerle aynı ise, birinci ifadenin içeriğini araştıran Case değiminden bir sonraki Case değimine kadar olan program satırları işletilir ve program akışı End Select değiminden sonraki satıra geçer. 

Örnek 8.2. : Yukarıdaki örneği bu Select Case değimiyle yapalım.

 

Private Sub Form_Load()

 

Dim n1,n2,n3,ort

n1=val(InputBox(“1.Sınav Notunu Giriniz:”, “Sınav”);

n2=val(InputBox(“2.Sınav Notunu Giriniz:”, “Sınav”);

n3=val(InputBox(“3.Sınav Notunu Giriniz:”, “Sınav”);

ort=(n1+n2+n3)/3

     Select Case ort

Case  ort<50

 MsgBox(“Kaldınız” &ort)

 Case ort>50

                        MsgBox(“Geçtiniz” &ort)

           

   End Select

End Sub

 

Örnek 8.3 : 1-3 arasında girilen sayıyı bulan programı yapanız?

 

Private Sub Form_Load()

Dim sayi

sayi=val(InputBox(“1 ile 3 arasında bir sayı giriniz.”);

Select Case sayi

Case 1 

 MsgBox(“Girdiğiniz Sayı 1”)

            Case 2

                        MsgBox(“Girdiğiniz Sayı 2” )

            Case 3

                        MsgBox(“Girdiğiniz Sayı 3” )          

   End Select

End Sub

 

8.1.3. IIF Yapısı

 

Bir değişkenin değeri iki durumdan birine göre değer alırsa IF yapısı yerine IIF kullanılabilir. Bu yapı bize daha az satırla aynı işi yapabilmemizi sağlar.

 

 

 

Yazılım : 

            IFF (Şart; Doğru ise; yanlış ise)

 

Örnek 8.4 :   

Private Sub Form_Load()

Dim n1,n2,n3,ort,son

     n1=val(InputBox(“1.Sınav Notunu Giriniz:”, “Sınav”);

     n2=val(InputBox(“2.Sınav Notunu Giriniz:”, “Sınav”);

     n3=val(InputBox(“3.Sınav Notunu Giriniz:”, “Sınav”);

     ort=(n1+n2+n3)/3

            son=IIF (ort<50, “geçtiniz”, “Kaldınız”)

MsgBox son

End Sub

 

8.1.4. Choose Yapısı           

Bir değişkenin aldığı değer bir sayıya bağlı ise bu yapıyı kullanmak daha uygun olur.

 Yazılım:

Sonuç= Choose(sayı, değer1, değer2, değer3, değer4,……,değerN)

 Örnek 8.5:  gun=Choose(GunNo, “Pazar”, “Pazartesi”, “Salı”, “Çarşamba”,    “Perşembe”, “Cuma”, “Cumartesi”)

8.1.5. Switch Yapısı

           Birden fazla şartı aynı anda kontrol etmek için kullanılır.

  Yazılım :           

Sonuç=Switch(Şart1, Değer1, Şart2, Değer2,…….,ŞartN, DeğerN)

            8.2.1. For-Next Döngüsü 

For-Next döngüsü sayacın başlangıç değerinden başlayarak bitiş değerine kadar istenilen miktarda artırılarak blok içindeki konutları çalıştırır.

 

Yazlım:

 

            For Sayac=BaşlangıçDeğeri to BitişDeğeri [Step Artırım]

                        Komutlar

            Next

 

Not:  Artma değeri verilmezse artış miktarı 1 olarak alınır.  

Örnek 8.6 :  1’den 10’a kadar olan sayıları toplayan programı yapınız?

 

Private Sub Form_Load()

 

Dim sayi,i

      For i=1 to 10

          sayi=sayi+i

      Next

            MsgBox sayi

End Sub 

8.2.2.While-Wend ve Do While- Loop Döngüsü

Bir şart gerçekleştiği sürece çalışması gereken program bloklarında kullanılırlar. 

 

Yazılım:                While Şart

                        Komutlar

            Wend

 Do While Şart

            Komutlar

Loop

Yukarıdaki her iki komutta da  şart gerçekleştiği sürece döngüde kalınır.

 Örnek 8.7: Klavyeden girilen 10 öğrencinin notlarına göre sınıf ortalamasını hesaplayan programı yapınız.

Private Sub Form_Load ()

Dim not (10) As Integer

Dim t As Integer

 i=1

                Do While i < = 10

                  Not(i) = InputBox(Str(i) & ”. Öğrencinin Notu”)

              t = t + not(i)

            Loop

ort=t/10

MsgBox ort

End Sub

 8.2.3. Do Until – Loop Döngüsü

Bu döngü yapısı diğerlerinden farklı olarak şart gerçekleşene kadar

çalışması gereken program bloklarında kullanılır.

 Yazılım :

            Do Until Şart

                        Komutlar

Loop

 8.2.4. Do-Loop While ve Do Loop Until Döngüsü

Bu döngü yapılarının diğerlerinden tek farkı şart döngüye girerken değil de çıkarken kontrol edilir. Yani döngü içerisindeki komutlar en az bir kez çalışırlar.

Yazılım :

            Do

                        Komutlar

            Loop Until Şart

 Do

            Komutlar

Loop While Şart

 8.2.5.      Döngü Kontrol İfadeleri

 8.2.5.1. Exit Do

Bu komut Do-Loop ve While Wend döngülerinden birinde bazı şartların gerçekleşmesi durumunda döngüden çıkmak için kullanılır.

 8.2.5.2. Exit For       

            For-Next döngüsü tamamlanırken bazı şartlar gerçekleştiğinde döngüden çıkmaya yarar.

 8.2.5.3. Exit Sub ve Exit Function 

           Exit Sub ve Exit Function değimleri alt program sonuna ulaşmadan alt programdan çıkmaya yarar.

 8.2.5.4. End

            Programı sona erdirir.

    

OpenGL

Bölüm 1: Sistem Altyapısı

A- SIMD mimarisi hakkında ön bilgi

Bu yazı grafik programlama ile ilgili olmasına rağmen, ilk önce elimizdeki sistemi tanıyarak ve bazı kurallar koyarak başlayacağız.

Bilgisayarlar 1983’den bu yana oldukça fazla gelişmelerine rağmen aynı taban üzerinde ayakta kalmaktalar. Süreklilik gerektiren işlerde oldukça yetenekliler, fakat düzensiz işlemlerde, örneğin değişken bir üç boyutlu sahneyi işlemekte, oldukça yavaşlar. Oyunlarda sıkça yapılan şeylerden birisi bu şekildeki verinin işlenmesi oldugu için, bu seride ilk yapacağımız şey, bilgisayarların ne olduğunu (ve olmadığını) öğrenmek ve bu kısıtlamanın üstesinden nasıl gelineceğini öğrenmek olacak.

Bir günümüz bilgisayarı:

1- Doğrusal ve uzun bloklar halindeki işlemleri daha hızlı yapabilir.

2- Ne kadar az hafıza erişimi yaparsa o kadar hızlı çalışır.

3- Elimizdeki “düzensiz” veri miktarı arttıkça adresleme hataları da o denli artar.

Tüm bunlar, Intel’in ve diğer firmaların şu anda kullandığı SIMD (Single Instruction Multiple Data = Tek komutta birden çok veri) tarzı işletim ile neredeyse tamamen örtüşen bir durum oluşturuyor. İlk kısıtlamamiz, bize uzun blokların tek seferde daha hızlı işlendiğini söylüyor, bu da tam olarak SIMD’nin yaptığı şey, uzun blokları tek seferde işlemek. Diğer iki kısıtlama bize adres çözme işleminin problemlerini, yani “cache miss” ve “misalign” sorunlarını anlatıyor. “Cache miss” ile kastedilen, bir adres çözme işlemi sonucu erişilecek verinin kaşe bellekte bulunmadığının anlaşılıp yeniden bir adres çözme işlemine yol açması. “Misalign” ise çözülen adresin 8 (ya da şimdilerde 16 byte)’ın katlarına denk gelmemesi, örneğin hafızanın 3. byte’ında bulunması sonucu gereksiz miktarda verinin birden çok kez okunmasına yol açmasına verilen isim.

Şimdi bu ufak tablodaki kısıtlamalardan kurtulmak için bu seri boyunca uyacağımız kurallara bir göz atalım:

1- SIMD ve/veya SIMD2 işlemlerine ağırlık vermek ya da bunlara dönüşebilir şekilde kod yazmak.

2- Veriyi daima “hizalanmış” hafıza adreslerinden başlatmak.

3- Veriyi daima 16 byte’ın katları olarak tutmaya çalışmak, mümkünse {X,Y,Z} gibi sırasız veri akışını {X[],Y[],Z[]} haline getirmek.

Üçüncü madde biraz karışık gelebilir. Tipik bir programda sakladığımız veri eğer

class nokta

{

      float x, y, z;

};

nokta benimNoktalarım[1024];

ise, bu SIMD için daha uygun olan:

class yogunNokta

{

      float x[1024], y[1024], z[1024];

};

yogunNokta benimNoktalarim;  

şeklinde yeniden düzenlenmelidir. Tabii bu şekilde statik veri ayrılması pek önerilen birşey olmadığı için bunu sadece konuyu açıklamak için verdiğimiz bir örnek olarak yorumlamanız gerekiyor, pratikte:

class yogunNokta

{

      float *x,* y, *z;

};

yogunNokta benimNoktalarim;

x=(float*) aligned_malloc( 1024 * sizeof(float), 16);

y=(float*) aligned_malloc( 1024 * sizeof(float), 16);

z=(float*) aligned_malloc( 1024 * sizeof(float), 16);

daha doğru bir yaklaşım. Buradaki aligned_malloc komutu 16 byte’ın katı olan bir adresten başlayacak şekilde bellek ayırmamızı sağlıyor.

B- Optimizasyon

Kullandığımız sistem, herşeyden önce, saf C/C++ kodunun daima en basit hedef işlemciye göre (zorlanmadıkça) derlendiği bir sistemdir. Yani yazdığımız aşağıdakine benzer bir satır, eğer biz derleyiciyi buna zorlamazsak, 80386’da hızlı çalışacak şekilde derlenir:

float fArray[16] = {1.0f, 4.6f, 12.0f, 43.0f, 61.0f, 52.0f, 2.0f, 1.0f, 3.0f, 4.0f, 6.0f, 13.0f, 421.0f, 54.0f, 654.0f, 1.0f};

for(unsigned long i=0; i<16; i++)

{

      fArray[i] *= 2.49f;

}

 

Bunun assembly karşılığı, standart derleyici çıktısı olarak:

xor   eax, eax

$loop1:

fld   DWORD PTR _fArray$[esp+eax*4+64]

fmul  DWORD PTR __real@401f5c29

inc   eax

cmp   eax, 16

fstp  DWORD PTR _fArray$[esp+eax*4+60]

jb    SHORT $loop1

olacaktır. Birinci kuralı ihlal ettik. Burada işlemcinin FPU kısmı kullanılarak aynı anda sadece bir sayı ile çarpma yapılmaktadır. Bunun yerine eğer bir P3/P4 derleyicisi ve el ile optimizasyon yöntemleri kullanırsak yukarıdaki kod şu şekli alır:

float fArray[16] = {1.0f, 4.6f, 12.0f, 43.0f, 61.0f, 52.0f, 2.0f, 1.0f, 3.0f, 4.0f, 6.0f, 13.0f, 421.0f, 54.0f, 654.0f, 1.0f};

float fPack[4] = {2.49f, 2.49f, 2.49f, 2.49f}; // 4 adet çarpan

float *p1,*p2;

p1 = &(fArray[0]);

p2 = &(fPack[0]);

_asm{

      mov ecx,4

      mov eax, p2

      movups xmm1, [eax]

      mov eax, p1

mLoop1:

      movups xmm0, [eax]

      mulps xmm0, xmm1

      movups [eax], xmm0

      add eax, 0x10 // 16, 4 tane 4 byte(float)

      loop mLoop1

};

Görüldüğü gibi artık tek komutta aynı anda dört çarpma yaparak daha uzun fakat daha hızlı bir kod elde ettik. Buradan da şu yeni kural çıkıyor:

Uzun kod daha hızlı çalışabilir.

Tabii bu kullanılan işlemciye göre değişeceği için OpenGL ya da DirectX gibi kütüphanelerde aynı rutin birden fazla işlemciye göre yeniden yazılmış şekillerde bulunurlar.

Bölüm 2: OpenGL  

A- OpenGL mi DirectX mi?  

Yeni programlamaya başlayanlar için çok daha az zahmetli olacağına inandığım OpenGL ile seriye başlamak istiyorum. DirectX her ne kadar daha “metale yakın” bir tarza sahip olsa da, burada okuyucunun derleyici ile yüksek bir ihtimalle beraber kurmuş olacağı OpenGL kütüphanelerini kullanacağız. Bu arada çoğu kullanıcının bir çeşit nVidia ya da ATI görüntü kartına sahip olduğunu ve en son OpenGL destekli (beta olmayan) sürücüleri yüklemiş olduğunu da varsayıyoruz.

OpenGL, DirectX’in aksine sürekli genişletilen (ve genişletilebilen) bir altyapıya sahip. Örneğin eğer bir firma bir kartı bu gün piyasaya çıkartır ve “raytrace destekliyor” olduğunu söylerse, bunun için (SGI ile konuşup eklentiyi kayıt ettirmenin yanında) tek yapmaları gereken bir adet “eklenti” yazmak ve bunu sürücülerine dahil etmek olacaktır. DirectX bu şekilde genişletilemez, sadece “yazılım ile render” eklentilerini kabul eder ve bunlar da donanınm ile çalışmazlar, sadece yazılımsal eklerdir ve “yeterince hızlı” değillerdir.  

OpenGL desteğimiz tam olduğuna göre, ilk OpenGL testimiz ile işe başlayabiliriz…  

B- Önce biraz ön bilgi  

OpenGL, bir “state machine” dir, yani her an verilen bir konumdadır ve sonraki komutlar bu konumda olunduğu göz önüne alınarak çalışır. Örneğin “ışıklandırma açık” ya da “kapalı” gibi. OpenGL aynı zamanda “batch” komut işletebilir, yani ardışık komutları saklayıp “bitir” sözcüğü ile birtilkte işletmeye alabilir.

Bu yapısı yüzünden OpenGL ile çalışırken her an hangi durumda olduğumuzu kesinleştirmek için uzun işlemler öncesi yeniden durumlarımızı ayarlarız. Örneğin ekrana yazı yazarken ışıklandırma gereksiz olduğu için kapatırken, sahne çizimini yapan kod parçası ışıkları tekrar açmalıdır. Her durum değişikliği bir çok hesaplama ve/ya da donanıma erişim gerektirdiği için çok iyi bir dizayn yaparak bunları minimum seviyede tutmakta yarar vardır.

Örneğin, her üçgeni çizmeden önce bir doku seçmek son derece yavaş olacaktır, bunun yerine aynı dokuyu paylaşan üçgenleri bir araya toplayıp tek seferde çizmek en iyi metodlardan biridir. Bu yüzdendir ki bazı basit BSP uygulamaları modern kartlarda yavaştır, çünkü sırasız ve düzensiz durum değişikliklerine yol açarlar.

Sıkça kullanılan bir yöntem de bir çok dokuyu tek bir büyük dokunun içerisine toplamaktır, böylece sadece bir kez doku seçilir.

Fakat bu iki probleme yol açar:

1- Doku gereğinden fazla büyük olur ve ya video belleğe sığmaz ya da yavaş erişime yol açar.

2- Doku ufak tutulur, fakat bu sefer ortalama kalite yarıya ya da daha kötü bir orantıya iner.  

Bir başka çare de büyük ve kalitesiz bir dokunun üzerine birden fazla ufak ve detaylı doku konumlandırmaktır. Bu tip dokulara “detay dokusu” adını verebiliriz. En hızlı yöntemlerden biri olmakla birlikte kendine has problemleri (detay dokusunun tekrarladığının belli olması gibi) vardır.  

İşte bu tip problemler varken, dokuları ufak tutup bunları bir “lightmap” (ışık dokusu) arkasına saklamak en basit ve hızlı çaredir. Böylece normal doku tekrarlasa bile, yüzeyin her noktasında farkı bir ışık değeri alacağı için tekrarsızmış gibi görünecektir.  

C- Henüz FPS söz konusu değilken…  

İlk yapacağımız şey, Windows alt sisteminden arınmış bir şekilde çalışmak olacak. GLUT kullanarak (openGL Utility Library = OpenGL yardımcı fonksiyon kütphanesi) oluşturduğumuz ilk örnek programımız iki adet üçgen ile bir kare çiziyor ve bunu ışıklandırıp renklendiriyor, fakat henüz doku içermiyor. Programımızın kodunu burada verip sizi yazma zahmetinden kurtarıyoruz:

Örnek1.zip

Bu kodu Visual C++ 6 ile derleyebilir ve ilk iki üçgenimize bakabilirsiniz. Fakat bundan fazlası için okumaya devam etmeniz gerekiyor…

D- Adım adım inceleme

Kodun bir kısmı (GLUT fonksiyonları) gözlerimizden uzakta OpenGL’i bir pencerede başlatıyor ve işin basit kısmı ile bizi başbaşa bırakıyor. Aşağıdaki satırlara bir göz atalım:

void display(void)

{

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      glColor4f(.2,.4,.2,1.0);

      glNormal3f(0.0, 1.0, 0.0);

      glBegin(GL_TRIANGLES);

      glVertex3f(-20.0,-15,20.0);

      glVertex3f(20.0,-15,20.0);

      glVertex3f(-20.0,-15,-20.0);

      glVertex3f(20.0,-15,-20.0);

      glVertex3f(-20.0,-15,-20.0);

      glVertex3f(20.0,-15,20.0);

      glEnd();

      glutSwapBuffers();

}

Burada sırayla şu işlemleri uyguluyoruz:

1- glClear: ekran dışı belleği sil (renk ve derinlik kanallarının ikisini de)

2- glColor4f: bundan sonraki noktalar için renk seç (yaklaşık yeşil, %100 opak)

3- glNormal3f: bundan sonraki noktaların işaret ettiği yönü belirt (tam yukarıya)

4- glBegin: buradan sonra verilen her üç nokta bir üçgene denk gelecektir (GL_TRIANGLES)

5- her 6 nokta için: glVertex3f: noktanın uzaydaki konumu

6- glEnd: bitir (burada OpenGL iki adet üçgeni “gerçekten” çizer)

7- glutSwapBuffers: GLUT ekran dışı belleği ekrana taşır (böylece çizdiğimizi görebiliriz)

Buradaki kod, tamamen “inline” (kod içerisinde) bulunan veri ile iki adet yeşil üçgen çiziyor. Dışarıdan dosya okuma gibi işleri sonraki yazılara bırakacağız o yüzden şimdilik böyle olması gerekiyor.  

E- Her noktaya farklı renk  

Yukarıdaki örnekte sadece bir adet glColor komutu yer alıyor. OpenGL bir “durum saklayan makina” (yukarıyı okuyun) olduğu için bu “durum” tüm çizim işlemleri boyunca geçerliliğini koruyor. Eğer iki adet farklı renkte üçgen çizmek istersek kodu şu şekilde değiştirmemiz gerekiyor:

glBegin(GL_TRIANGLES);

      glColor4f(.2,.4,.2,1.0);

      glVertex3f(-20.0,-15,20.0);

      glVertex3f(20.0,-15,20.0);

      glVertex3f(-20.0,-15,-20.0);

      glColor4f(.2,.2,.4,1.0);

      glVertex3f(20.0,-15,-20.0);

      glVertex3f(-20.0,-15,-20.0);

      glVertex3f(20.0,-15,20.0);

glEnd();  

Böylece bir yeşil bir mavi üçgenimiz oldu. Aslında bir adım daha ileriye giderek her noktaya bir renk verebiliriz:

glBegin(GL_TRIANGLES);

      glColor4f(.2,.4,.2,1.0);

      glVertex3f(-20.0,-15,20.0);

      glColor4f(.4,.4,.2,1.0);

      glVertex3f(20.0,-15,20.0);

      glColor4f(.4,.4,.4,1.0);

      glVertex3f(-20.0,-15,-20.0);  

      glColor4f(.2,.2,.4,1.0);

      glVertex3f(20.0,-15,-20.0);

      glColor4f(.2,.4,.4,1.0);

      glVertex3f(-20.0,-15,-20.0);

      glColor4f(.4,.2,.4,1.0);

      glVertex3f(20.0,-15,20.0);

glEnd();

Değişikliğe dikkat edin, üçgenlerimiz yine bir durum değişkenine uyarak “Gouraud” ışıklandırıldılar, yani kenar noktaları arasında renk değerleri doğrusal olarak dolduruldu.

Bu durumu kontrol eden komut:

glShadeModel(GL_SMOOTH)

satırı. İsterseniz şimdi diğer bölüme geçip, daha önceden ihmal ettiğimiz “durum” ayarlarına bir göz atalım.

F- Sahnenin çizim için ayarlanması

Programımızın yukarıdaki kısmına gelmeden önce kısa bir rutin ile bir takım ayarlar yapmıştık. Bu ayarlar, OpenGL’in aktardığımız veriyi nasıl yorumlayacağını düzenlemek üzere bir ihtiyaç doğdukça yapılan türden, örneğin kameranın konumu değiştiği zaman tekrar bir kamera transformasyonu ayarlamamız gerekiyor. Aşağıdaki kod sırası ile anlatılan işlemleri yapmakta:

// derinlik testi açık

glEnable(GL_DEPTH_TEST);

// ışığı renklendir

glLightfv(GL_LIGHT0, GL_SPECULAR, isik_renk);

// ışığı konumlandır

glLightfv(GL_LIGHT0, GL_POSITION, isik_konum);

// ışığı aç

glEnable(GL_LIGHT0);

// OpenGL ışıklandırma açık

glEnable(GL_LIGHTING);

// yüzey saklama açık

glEnable(GL_CULL_FACE);

// arka yüzeyleri sakla

glCullFace(GL_BACK);

// ışık ve rengin çalışması için gerekli

glEnable(GL_COLOR_MATERIAL);  

// gouraud tipi ışıklandırma

glShadeModel(GL_SMOOTH);

// projeksiyon

glMatrixMode(GL_PROJECTION);

gluPerspective(

      60.0, // 60 derece bakış açısı

      1.0,  // pixel deformasyon orantısı (y/x)

      1.0,  // yakın düzlem

      10000.0); // uzak düzlem  

// kamera transformasyonu

glMatrixMode(GL_MODELVIEW);

gluLookAt(

      10.0, 20.0, 30.0, // göz noktası

      0.0, -20.0, 0.0,  // hedef

      0.0, 1.0, 0.);      // yukarı  

Burada en önemli durum değişkenimiz GL_LIGHTING. Eğer bu durumu “enable” ile açık duruma getirmezsek pek birşey görmemiz mümkün değil. Sahnede en az bir adet ışık kaynağı bulunması gerekiyor ki cisimlerin derinlik ve konumlarını algılamamız kolay olsun. Tabii ışıkları aktif hale getirmeden önce glLight() ile konum ve renk bilgisini vermemiz gerekiyor. Göreceğimiz üzere glLight‘ın ikinci parametresi pozisyon ya da renk bilgisini vermekte olduğumuzu belirtiyor.  

gluLookAt, kamerayı konumlandırmak için kullanabileceğimiz en kolay rutin ve çok basit 3 parametre alıyor:  

gluLookAt( kamera_pozisyonu, hedef_pozisyonu, yukarı_vektörü);  

Burada “yukarı_vektörü”, o anki projeksiyon düzleminin “yukarısı” için kabul ettiği yönü tarif etmek için kullanılıyor. Bunun ile oynayarak, örneğin bir oyunda karakterin adımları ile oluşan sağa-sola yaylanma hareketini (ve bu nedenle oluşan kamera sarsıntısını) vermek mümkün.  

Bütün bunları bir araya koyarsak, temel bir OpenGL programının yapısı şu şekilde olmakta:

1- Sahneyi (ışık ve kamera) hazırla

2- Her ekran tazeleme işlemi için, sahneyi sil ve baştan çiz

Bu şekilde özetlediğimiz kadarıyla, OpenGL dünyanın en kolay grafik arabirimlerinden biri gibi görünmekte. Aslında gücünü de bu basit yapısından alıyor, söz ile anlatabileceğimiz her grafik problemini OpenGL kullanarak ekrana dökmek mümkün.  

G- OpenGL komutlarının sözdizimi  

Şu ana kadarki komutların bazıları, eğer fark ettiyseniz, sonlarında 2f, 3f gibi ekler içermekte. Bunun amacı, o komuta verilecek olan parametrelerin türünün kullanıcı tarafindan belirtilebilmesini sağlamak. Örneğin bir glColor4f komutu, aşağıdaki şekilleri alabilir:

void glColor3b(GLbyte red, GLbyte green, GLbyte blue);

void glColor3d(GLdouble red, GLdouble green, GLdouble blue);

void glColor3f(GLfloat red, GLfloat green, GLfloat blue);

void glColor3i(GLint red, GLint green, GLint blue);

void glColor3s(GLshort red, GLshort green, GLshort blue);

void glColor3ub(GLubyte red, GLubyte green, GLubyte blue);

void glColor3ui(GLuint red, GLuint green, GLuint blue);

void glColor3us(GLushort red, GLushort green, GLushort blue);

void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);

void glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);

void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);

void glColor4i(GLint red, GLint green, GLint blue, GLint alpha);

void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha);

void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);

void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha);

void glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha);  

Kural gereği kullanılan ekleri atarak komutun adını glColor() olarak telaffuz ederiz. Anlaşılacağı üzere eklenen kısaltmalar bize parametrelerin 8, 16, 32 ya da 80(ya da 96) byte uzunluğunda olduğunu belirtiyor. Bu kullanılan renk aralığının hassasiyetini artırmaz, sadece kullanıcıya bir kolaylık sağlar. Dahili olarak tüm renkler ekran kartlarında tamsayı ya da “32 bit float” olarak işlenir.  

Bütün parametre alan komutlar bu şekilde isimlendirilirer ve benzer kurallara uyarlar. Diğer komutların yazılışı için Visual C++ içerisinde yer alan yardım dokümanına ve gl.h dosyasına göz atmanızı tavsiye ederiz.  

OpenGL, eklerle sürekli genişlemektedir. Bu yüzden yeni komutların yazılışı, parametreleri vb vb için <a href=”http://www.opengl.org/”>www.opengl.org</a> ya da SGI’daki dokümanlardan faydalanmamız gerekiyor.

H- Sonuç  

Buraya kadar temel bilgileri edindik. Elimizdeki örnek kodun çizim kısmını değiştirerek, örneğin diskten veri okuyarak bir çok cismi çizmek mümkün. Fakat bu şekilde çok hızlı görüntü elde etmek olanaksız olduğu için, bir sonraki yazımızda öncelikle sistem belleğinde bulunan üçgen listelerinin çizimine başlayacağız. Ardından, “strip” yapısını anlatıp bunun avantaj / dezavantajlarına değinecek ve ilk doku kaplı yüzeyimizi çizeceğiz.  

Tüm sorularınız için email adresim : engin@vividimage.co.uk