Home Index Search Links About Us
[LinuxFocus Image]
[Navegation Bar]
  Duyumlar   Belgelikler   Kuruluşlar  Öğütler  

GLUT Programlama: Pencereler ve Canlandırımlar

Yazar: Miguel Angel Sepúlveda

Çeviri: Emre Demiralp


Giriş

Başlatımlar

Olay İşleme

Canlandırım Örneği



GLUT Yuvasayfası
GLUT Yazarı
GLUT-3.6 kaynakları

Giriş

Tasarımsal nedenlerden dolayı OpenGL özelliklerinde pencere bağımlılığından kaçınılmıştır. Böylelikle oluşan arayüz taşınabilir, veriyollarıyla bezenmiş bir 2 ve 3 boyutlu görüntüleştirme kitaplığı niteliğindedir. Pencere açma ve görüntüleştirme yerel pencere sistemine kalmış bir konudur. OpenGL kitaplığı, yerel sistemle, yardımcı kitaplıklar aracılığıyla iletişimde bulunur. Sözgelimi, GLX yardımcı kitaplığı OpenGL ile X pencere sistemi arasında iletişim sağlar. 

OpenGL elaygıt takımı (GLUT: OpenGL Utility Toolkit), pencere sisteminden bağımsız OpenGL programları yazmak için ANSI C ve FORTRAN bağlantılarûndan oluşur. Bu yazılım Mark J. Kilgard tarafından yazılmış olup OpenGL tanımlamalarında açık kalmış olan büyük bir boşluğu örtmektedir. Erek ortamdan (target platform) bağımsız olarak ortak bir pencere sistemi kullanımına olanak sağladığı için GLUT geliştiricilerine şükran borcumuz bulunmaktadır.  

GLUT göresel olarak küçük ve öğrenmesi kolay bir yapıdır. Tasarımı iyi olup yazarı tarafından çok güzel bir bilgi dağarcığı da hazırlanmış bulunmaktadır. Bu nedenle, burada, Linux Focus'ta bir yazı serisine başlamak pek de anlamlı gözükmeyebilir. Ciddi program geliştirmek isteyenlere Mark'ın bilgi dağarcığını okumalarını salık veririz. Burada, bu GLUT sütununu yazmaktaki amacımız GLUT kitaplığını ve onun kullanımını, örneklerle adım adım ve bu derginin OpenGL serisine yandaş bir okuma kaynağı olarak sunmaktır. Bu yaklaşımın yararlı bir katkı sağlayacağını ve daha çok sayıda program yapımcısını OpenGL-Linux vagonuna binmeye iteceğini ummaktayız. Yine de, Mark'ın bilgi dağarcığını iyi bir kaynak olarak edinmenizde yarar bulunmaktadır. 

GLUT API, OpenGL gibi, bir durum motorudur. Bunun anlamı, GLUT'un uygulamanın çalıştırılması sürecinde etkin olan durum değişkenlerine sahip olduğudur. GLUT motorunun başlangıç durumları bir çok uygulamaya uyabilecek biçimde seçilmiştir. Program, uygun gördükçe, durum değişken değerlerini değiştirebilir. Herhangi bir GLUT fonksiyonunun uyarılması durumunda, fonksiyonun etkimesi o andaki durum değişkenlerinin değerlerine göre ayarlanır. GLUT fonksiyonları kolay yapıda olup yalnızca bir kaç parametre alırlar. Fonksiyonlardan genellikle gösterici (pointer) döndürülmez ve fonksiyonlara gönderilen göstericiler ise yalnızca katar ve geçirgen olmayan fontlar için olanlarla kısıtlanmışlardır. 

GLUT fonksiyonları, işlevselliklerine göre, bir kaç alt API'ye sınıflandırılabilirler: 

  • Başlatım 
  • Başlangıç Olay İşlemesi 
  • Pencere İşletimi 
  • Örtükatman (overlay) İşletimi 
  • Mönü İşletimi 
  • Geriçağırış Kayıdı 
  • Renk İndeksi, Renk Haritası İşletimi 
  • Duruma Geridönüş 
  • Font Görüntüleştirimi 
  • Geometric Biçim Görüntüleştirimi 
Bu yazıda, basit bir OpenGL programını başlatmak için gerekli olan başlatım, pencere işletimi, olay işleme fonksiyonlarından bazılarını inceleyip anlamaya çalışacağız. 

Başlatımlar

GLUT kullanan tüm OPenGL programları GLUT durum motorunu başlatacak biçimde başlamalıdırlar. GLUT başlatım fonksiyonları glutInit- önekine sahip olmalıdırlar. Ana başlatım yordamı glutInit'dir: 
Kullanım 
  glutInit(int **argcp, char **argv); 
  argcp anaprogramdan, programın düzeltilmemiş argc değişkenine bir göstericidir.Döndürüldüğünde argcp tarafından gösterilmekte olan argcp değeri güncellenir. Bunun nedeni, glutInit fonksiyonunun, GLUT kitaplığı ile ilgili olan güdümsatırı seçeneklerini çekip çıkarmasıdır. Sözgelimi, X pencere sistemi ortamında, X pencere sistemiyle ilgili seçeneklerden GLUT'la bağlantılı olanların algılanması gibi
  argv program'ın, anaprogram için, düzeltilmemiş argv değişkenidir.   

glutInit GLUT durum değişkenlerinin başlatımını ve pencere sistemi ile bir oturum için iletişimin sağlanmasını üstlenir. glutInit'ten önce başlatılan bir kaç yordam varolup bunlar glutInit- önekine sahiptirler. Bu yordamlar benimsenen pencere başlatım durumunu ayarlamakta kullanılırlar.  Sözgelimi: 
Kullanım 
  glutInitWindowPosition(int x, int **y); 
  glutInitWindowSize(int width, int **height); 
  x,y  = piksel türünden pencerenin ekrandaki konumu (sol üst köşe)  
  width,height  piksel türünden pencere en ve boyu. 

Tüm OPenGL uygulamasında kaçınılmaz olarak bulunan başka bir başlatım yordamı, (glutInitDisplayMode()) daha bulunmaktadır: 
Kullanım 
  glutInitDisplayMode(unsigned int mode); 
  mode güsterim modu olup GLUT güsterim modu bit maskelerinin bit türü bir OR'lamasıdır. Olabilir bit maske değerleri aşağıda verilmektedir 
GLUT_RGBA  Bir RGBA mode pencere seçer. Bu, ne GLUT_RGBA ne de GLUT_INDEX belirtilmedikçe, benimsenen değer olarak kalır. 
GLUT_RGB  GLUT_RGBA ile aynı. 
GLUT_INDEX  Renk indeks pencere modunu seçer. GLUT_RGBA'ya baskındır. 
GLUT_SINGLE  Tek bir tamponlu pencere seçer. Bu benimsenen yapıdır. 
GLUT_DOUBLE  Çift tamponlanmış bir pencere seçer. GLUT_SINGLE'a baskındır. 
GLUT_ACCUM  Depolama tamponlu bir pencere seçer. 
GLUT_ALPHA  Renk tamponuna(larına) alfa bileşenli bir pencere seçer. 
GLUT_DEPTH  Derinlik tamponlu bir pencere seçer. 
GLUT_STENCIL  Örüntü yedekleme tamponlu bir pencere seçer. 
GLUT_MULTISAMPLE  Multismapling destekli bir pencere seçer. 
GLUT_STEREO Bir stereo pencere seçer. 
GLUT_LUMINANCE "luminance" renk modelli bir stereo pencere seçer. 
Eğer bu özelliklerin bazılarına yabancı iseniz dert etmeyin, şimdi ya da sonra, bunlardan sözedeceğiz. Şimdi bir kaç örnek üzerinde duralım.  Önce, tek darbe görüntüleme uygulaması için basit bir başlatım: 

#include <GL/glut.h> 

void main(int argcp, char **argv){ 

/* Set window size and location */ 
glutInitWindowSize(640, 480); 
glutInitWindowPosition(0, 0); 

/* Select type of Display mode:  
   Single buffer & RGBA color */ 
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE); 

/* Initialize GLUT state */ 
glutInit(&argcp, argv);  

.....more code 

}; 

İkinci olarak bir canlandırım programı: 

#include <GL/glut.h> 

void main(int argcp, char **argv){ 

/* Set window size and location */ 
glutInitWindowSize(640, 480); 
glutInitWindowPosition(0, 0); 

/* Select type of Display mode: 
   Double buffer & RGBA color */ 
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); 

/* Initialize GLUT state */ 
glutInit(&argcp, argv);  

.....more code 

}; 

Bu iki örneğe, GLUT hakkında daha çok şey öğrendikçe geri döneceğiz. Bu ikisi arasındaki ana ayrılık, ikinci örnekte gösterimin bir çift tampon modunda başlatımıdır. Bu durum canlandırımlar için idealdir, çünkü bu yapı canlandırım sürecindeki kırpışmaları ortadan kaldırır. 

Olay İşleme

Yukarıda sözedildiği gibi, GLUT bir durum motorudur. Şimdi de onun olay geliştiren bir motor olarak da tasarlandığını öğreneceğiz. Bunun anlamı, bir sayaç'ın ya da sürekli bir döngünün uygun başlatımlar sonrasında devreye girıdiğidir. Bunlar, GLUT'a belirtimi yapılan tüm olay ve süreçlerin başlatılmasını sağlarlar. Olaylar şunlardır: tıklatılan bir fare, kapatılan bir pencere, bir pencerenin yeniden biçimlendirilmesi, imleç hareketi, basılan klavye tuşları, ve daha da ilginci, hiçbirşeyin olmadığı boş olay. Olası olayların her biri GLUT sayaç ya da olay geliştirme döngüsünün değişkenlerinden birine kaydedilmelidir. Böylece, bu olayların tetiklenip tetiklenmediği sürekli denetlenebilir duruma gelmiş olur. 
 
Sözgelimi, "fareyi tıklat"ı bir olay olarak GLUT'a kaydedip gözlemleyebiliriz. Olaylar geriçağırış kayıt yordamlarıyla kaydedilirler. Tümünde yazımkuralı glut[someEvent]Func biçimindedir. Fare tıklama durumunda bu glutMouseFunc biçiminde olacaktır. Bir geriçağırış kaydı GLUT motoruna hangi kullanıcı tanımlı fonksiyonun olayın tetiklenmesi durumunda çağırılacağını söyler. Dolayısıyla, farenin sol (ya da sağ,..) tuşu tıklatıldığında ne yapılacağını tanımlayan MyMouse adlı kendi yordamımı yazacak olursam o zaman geriçağırış fonksiyonumu main() içinde glutInit() sonrasında "glutMouseFunc(MyMouse);" deyimini kullanarak kaydedebilirim. 

GLUT içinde hangi geriçağırma fonksiyonlarına ve olaylara olanak sağlandığını daha sonraya bırakalım. Bu anda önemli olan nokta uygulamamızdaki tüm önemli olaylar kaydedildikten sonra GLUT'un olay işleme yordamı olan glutMainLoop()'un uyarılmasıdır. Bu fonksiyonun geri dönüşü yoktur, programımız temelde sonsuz bir döngüye girer. Bu döngü gerekli olan önceden kayıtlı geriçağırma fonksiyonları çağırır. Tüm OpenGL uygulamalı main() fonksiyonları, bu nedenle, bir glutMainLoop() deyimi ile sona ermelidir. Dolayısıyla, bizim canlandırım şablonumuzda: 

#include <GL/glut.h> 

void main(int argcp, char **argv){ 

/* Initialize GLUT state */ 
glutInit(&argcp, argv);  
glutInitWindowSize(640, 480); 
glutInitWindowPosition(0, 0); 

/* Open a window */ 
glutCreateWindow("My OpenGL Application"); 

/* Select type of Display mode:  
   Double buffer & RGBA color */ 
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); 
 

/* Register Callback Functions */ 
..... 

/* Start Event Processing Engine */ 
glutMainLoop(); 
}; 

Görüldüğü gibi, uygulamaya önceden sözü edilmeyen fazladan kod eklemiş bulunmaktayım. Bu, glutCreateWindow(char **name), GLUT'un pencere işletim yordamlarından biridir. Bu, işte, OpenGL & GLUT tasarım felsefesinin en çok hoşuma giden bir yanıdır. Yalnızca adına bakarak yordamın ne yaptığı hakkında bilgi edinmek mümkündür!. Ayrıca, tabandaki pencere sistemine OpenGL uygulamamız için pencere açtırma güdümünü de gönderebilmektedir. Açılacak pencere bir katar ile aktarılan ada sahip olacaktır. X pencere sisteminde bu ad pencerenin sol üst köşesine yazılacaktır. GLUT'un pencere işletim bölümü inceleyeceğimiz daha bir çok fonksiyon barındırmaktadır. Bu an için burada verilen yeterlidir. Öte yandan, burada başlatım yordamlarını onların glutInit()'den sonra da yerleştirilebileceğini göstermek üzere yeniden düzenlemiş bulunmaktayım. 

Olaylara dönelim... Şimdi, tüm canlandırım programları için çok temel olan iki geri çağırma kayıt fonksiyonundan sözetmek istiyorum. Bunlar gösterim fonksiyonunu varolan pencere için düzenleyen glutDisplayFunc ve boş geriçağırma'ları düzenleyen glutIdleFunc fonksiyonlarıdır. Her iki kayıt fonksiyonu da void *(void) türü birer fonksiyondurlar. Diyelim ki canlandırım şablonumuz için iki tane ek geriçağırma fonksiyonu yazıyoruz. Bunlar, görüntümüzü pencere üzerine çizen OpenGL yönermelerini devreye sokan void MyDisplay(void) ve kullanıcıdan herhangi bir veri girişi olmadığında çağrılan, yani GLUT'un olay işleme makinası sonsuz döngüde (glutMainLoop()) ilerlerken tetiklenmiş bir olay bulamadığında devreye sokulan, void MyIdle(void) fonksiyonları olarak düşünülebilirler. Bir canlandırım programında neden bir Boş geriçağırma fonksiyonu kaydına gereksinim duyuyorum dersiniz? Yanıt şöyledir: Çünkü, canlandırım süresince gösterilen, görüntülerin (çerçevelerin) her birini, kullanıcıdan gelecek verilerden bağımsız olarak düzeltmek istersem OpenGL programının çalıştırılması süresince sık sık çağrılarak çerçeveleri MyDisplay() çizilmelerinden önce değiştirebilen bir fonksiyon (boş geriçağırma) fonksiyonu varolmalıdır.  

Canlandırım Örneği

Sonuçta, işte, canlandırım için basit bir şablon: 
#include <GL/glut.h> 

void MyIdle(void){ 
/* Some code to modify the variables defining next frame */ 
.... 
}; 

void MyDisplay(void){ 
/* Some OpenGL code that draws a frame */ 
.... 
/* After drawing the frame we swap the buffers */ 
glutSwapBuffers(); 
}; 

void main(int argcp, char **argv){ 

/* Initialize GLUT state */ 
glutInit(&argcp, argv);  
glutInitWindowSize(640, 480); 
glutInitWindowPosition(0, 0); 

/* Open a window */ 
glutCreateWindow("My OpenGL Application"); 

/* Select type of Display mode:  
   Double buffer & RGBA color */ 
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); 

/* Register Callback Functions */ 
glutDisplayFunc(MyDisplay) 
glutIdleFunc(MyIdle) 

/* Start Event Processing Engine */ 
glutMainLoop(); 
}; 

Gördüğınüz gibi MyDisplay sonuna yeni bir GLUT yordamı, glutSwapBuffers(), eklemiş bulunmaktayım. Bu, canlandırımlarda çok yararlıdır. Burada, bir gösterilen diğeri gizlenen, çift tampon modunda pencere kullanıyoruz. Bu durumda OpenGL yönermelerinin görüntülenmesi daima gizli tampon içine yapılır. glutSwapBuffers, çağrıldığında, tamponları değiştokuş ederek çizileni pencere içinde görüntüler. Bu teknik, bilgisayar canlandırımlarında, çerçeve içeriğinin satır satır oluşturumunu insan gözünden saklaması nedeniyle, genellikle yeğlenir. 

Artık, OpenGL uygulamalarını yazmaya başlamak için yeterince malzeme elimizde bulunmaktadır. Eksik olan tek şey MyDisplay() içindeki, gerçekte çizimi gerçekleştiren, OpenGL yönermeleridir... ama bu da başka bir öyküdür.;-). 

GLUT programlama üzerine olan gelecek yazıda, GLUT'un Pencere İşletimi bölümünde bize sağlanan işlevsellik üzerinde daha derinlemesine duracak ve aynı pencerede çok sayıda görüntü oluşturumu üzerinde duracağız. Ayrıca, taşınabilirliklerini vurgulayarak pro'lar ve con'ları da içererek, mönülerin kullanımını da göreceğiz


Daha çok bilgi için:
© 1998 Miguel Angel Sepulveda
Bu sanal yörenin bakımı Miguel A Sepulveda tarafından yapılmaktadır..