Anasayfa Eğitseller Oyun Yapımı OpenGL'de Pencere Yaratmak

OpenGL'de Pencere Yaratmak PDF Yazdır e-Posta
Kullanıcı Değerlendirmesi: / 2
ZayıfEn iyi 
Eğitseller - Oyun Yapımı
Cuma, 18 Ocak 2008 23:00


OpenGL'de Pencere Yaratmak (Çeviri)

 

Bu eğitselde OpenGL’de nasıl bir boş pencere yapılacağını öğreneceksiniz, ya da en azından nasıl yapıldığını göreceksiniz :) Highlighted c++ syntax kullanacağım bu eğitselde. Eğer c++ bilginiz yoksa ama başka bir programlama dilini biliyorsaniz hic endişelenmeyin .OpenGlsyntax neredeyse diger programlama dillerine benziyor. Başlamadan önce birkaç şey daha belirtmek istedim. İlk olarak pencereyi kullanmak için pencere yapmanıza gerek yok yani vazgeçmeyin. Eğer tam olarak anlamadıysanız bu gelişmiş (karışık) kodu, bunu bir sonraki eğitselde daha kolay anlayabileceksiniz. Ama InitGL ve DrawGLScene fonksiyonlarına calışmanız lazım çünkü onları ileriki eğitsellerde kullanacağiz. Bu kodun büyük bir bölümü orijinal olarak Neon Helium tarafından yazıldı. Ve neredeyse aynı kod olan Nehe'nin Ders 5’i bulabilirsiniz. Ben bu pencereyi kullanıyorum çünkü bayaği iyi bir sanat parçası ve internette bulabileceğiniz en popüler OpenGL pencere kodudur. Bu pencere kodunu kullanarak kendi işinizi başka sitelerdeki OpenGL programlama örnekleriyle karşılaştırmak daha kolay olacaktır, bu benim işime yaradı...

 

1# Hadi yapalım şunu! OpenGL’in bilgisayarınızda derlenmesi için header ve library dosyalarının eklenmesi gerekiyor. Eğer bunlar yok ise buradan indirebilirsiniz OpenGL SDK’yı. Microsoft Visual Studio’da gereken lib dosyalarını ekleyebilirsiniz şu şekilde:

 

Project>Ayarlar menüsü  Link tabının altında. Ya da kod olarak ta ekleyebilirsiniz, aşağıda gördüğünüz gibi. Bunu sizin için source kodda yaptım ama bu belki sizin için ilk defa bir lib dosyasını eklemek olabileceğinden dolayı size biraz anlatıyım. Lib dosyaları birer library dosyalarıdır ve bize dll dosyalarını programlama yetkisi  verirler. Bir programcıya göre dll dosyaları önceden derlenmiş birçok kullanışlı fonksiyonlarının olduğu bir sınıfa benzer. Bir lib dosyası “pragma call” tarafından aşağıdaki gibi eklenir.

 

#pragma comment(lib, "opengl32.lib")

#pragma comment(lib, "glu32.lib")

#pragma comment(lib, "glaux.lib")

 

#include "windows.h"       // Windows Baş Dosyası (Header File)

#include "gl\gl.h"     // OpenGL Library’si İçin Baş Dosya (Header File)

#include "gl\glu.h"    // GLu32 Library’si İçin Baş Dosya (Header File)

#include "gl\glaux.h"  // Glaux Library’si İçin Baş Dosya (Header File)

 

 2# Sonra değişken bildirmemiz gerekiyor. Penceremize bir handle , bir device content ve bir OpenGL rendering context gerekiyor. OpenGL Rendering Context’in tanimi hRC’dir. Her OpenGL programının bir Rendering Context’e ihtiyacı vardır. Rendering Context , OpenGL’in aramalarını Device Content’a bağlayan linktir. Programın bir pencere  çizmesini sağlamak için window handler’dan Device Context yapmanız lazım. Windows Device Context’in tanimi hDC’dir. DC pencereyi GDI (Graphics Device Interface)’e bağlar . RC OpenGL‘i DC’ye bağlar. Biz aynı zamanda klavye sıralanışını bildiririz, boolean’ı aktifleyip (set to true eğer uygulama calışıyor ise) ve bir tam ekran bayrağı.. (set to true if the application is running)

 

HDC        hDC=NULL;   // Özel GDI Device Context

HGLRC      hRC=NULL;   // Kalıcı Rendering Context

HWND       hWnd=NULL;  // Window Handle’ımızı Tutuyor

HINSTANCE   hInstance;  // Uygulamanın Örneğini Tutuyor

bool    keys[256];          // Klavye Düzeni İçin Rutin

bool    active=TRUE;     // Pencere Aktif Bayrağı TRUE’ya Ayarlanmış ***                                                  

bool     fullscreen=TRUE;    // Tam Ekrana Ayarlanmış Default Tarafından

 

***Default Tarafından

 

3#Sonraki yapacağımız şey ise pencere prosedür fonksiyonunu ilan etmek. Bu fonksiyon pencereye gönderilen bütün mesajları idare eder. Eğer bi tuşa basarsak ya da fareyi oynatırsak penceremizin nasıl tepki vereceğini bildirmemiz lazım.

 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //WndProc’ün ilanı

 

4# ReSizeGLScene fonksiyonu OpenGL ekranımızı yeniden boyutlandırmak için kullanılır. Aynı zamanda bu fonksiyon bizim “sıfıra bölmek” işlemini yapmamamızı ve programın göçmesini engeller. Yeni viewport’umuzu yenileyip ilan etmek için ilk olarak istediğimiz sahnenin enini ve boyunu glViewport fonksiyonuna girmemiz lazım. Ondan sonra güzel bir bakış açısı yaratıp uzaklaştıkça birşeylerin küçülmesi gibi.

 

glMatrixMode(GL_PROTECTION) kısaca kodun yanındaki çizgiler matrix projeksiyona etki edeceğini tanımlıyor. Projection matrix’in işlevi sahneye perspektif yerleştirmektir. glLoadIntentity reset’e benzer, seçilmiş olan matrix’i eski durumuna orjinal konumuna getirir. glLoadIdentity çağırıldıktan sonra biz görüş açısını gluPerspective ile ayarlıyoruz. (OpenGL kamera makalesinden okuyabilirsiniz)

 

glMatrixMode(GL_MODELVIEW) yeni tansformasyonların matrix’in model görünümüne etki edeceğini tanımlıyor. Matrix model görünümünün açılımı, objemizin bilgisinin tutuldugu yerdir. Son olarak matrix model görünümünü resetliyoruz. Eğer bunları anlamıyorsanız önemli değil… Sadece şunu anlayın ki bunların yapılması gerek eğer pencere görünümü istiyorsanız perspektifinizde.

 

GLvoid ReSizeGLScene(GLsizei en, GLsizei boy)

{

    if (height==0)                    //0’a Bölünmesini Engelliyor     {

        height=1;                      // Boyu 1’e Eşitliyor

    }

 

    glViewport(0,0,width,height);     // Şimdiki Viewport’u resetliyor

 

    glMatrixMode(GL_PROJECTION);      // Projeksiyon Matrix’i seçiyor

    glLoadIdentity();                 // Projeksiyon Matrix’i Resetliyor

 

    // Pencerenin Oranını Hesaplıyor (Aspect Ratio)

    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

 

    glMatrixMode(GL_MODELVIEW);       // Modelview Matrix’i Seçiyor

    glLoadIdentity();          // Modelview Matrix’i Resetliyor         }


5# Şimdiki fonksiyonu çok kullanacağız! Burda bütün OpenGL uygulamalarının sıfırlamalarını yapacağız (initialization). Ekranın rengini seçeceğiz, depth buffer’ı (Z-Buffer) açacağız, pürüzsüz gölgelendirmeyi açacağız, vb. Bu fonksiyon OpenGL penceresi tamamen bitirilmeyinceye kadar kullanılmayacaktır (called). Sonraki çizgi pürüzsüz gölgelemeyi açıyor. Renk değeri 0.0f’den 1.0f ’e kadar. 0.0f en siyahı ve 1.0f de en parlak olanı. Bu fonksiyon RGBA değerlerini kullanıyor. İlk parametre KIRMIZI yoğunluğunu gösteriyor, ikinci parametre YEŞİL ve üçüncü MAVİ. Ne kadar numaranın değeri 1.0f’e yakın ise o kadar parlak olur o renk. Son numara Alpha değeridir. Ekranı temizlemeye gelince, 4’üncü numarayı kafaya takmayalım. Şimdilik 0’da bırakın. Değişik renkler elde edersiniz üç esas rengi karıştırarak(kırmızı, yeşil, mavi). Şimdiki 3 fonksiyon depth buffer için. Depth buffer’ı ekrana katmanlar olarak düşünün. Depth buffer objelerin ekrana ne kadar derin olduklarını hatırlar (ayarlar) herneyse siz ne demek istediğimi anladınız :). İlk hangi objenin çizileceğini hatırlar (keeps the track)  ve ekrana çizdiğiniz üçgenin arkasına kare üçgenin önüne gelmemesini sağlar. Depth buffer OpenGL’in çok önemli bir parçasıdır, ve genel olarak 3B programlamanın. Depth buffer’ı bu uygulamada kullanmayacağız çünkü gerekmiyor, ama ileriki eğitsellerde daha gelişmiş şeyler yaptıktan sonra bir depth buffer’ı kaptın görün farkı… Setup fonksiyonunu başka ne amaç için kullanabiliriz ileride?! 3B modeli render yapmak için ilk olarak modeli yüklememiz lazım… Model yükleme fonsiyonunu burada cağırmak cok üunasip olur, ama şimdilik biz sadece boş bir pencere ile ugraşıyoruz…      


int InitGL(GLvoid)             // Bütün OpenGL Setup Buraya Gelir

{

    glShadeModel(GL_SMOOTH);          // Pürüzsüz Gölgelendirmeyi Aç

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);     // Siyah Arkaplan

    glClearDepth(1.0f);                       // Depth Buffer Setup

    glEnable(GL_DEPTH_TEST);          // Depth Testini Aç

    glDepthFunc(GL_LEQUAL);                   // Yapılacak Depth Testi

 

    //Çok Güzel Görüş Açısı Hesaplamaları    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    return TRUE;               // Başlatma Yolunda Gitti (initialization)

}

 

6# Off! Sonunda render fonksiyonu... Bu benim en favori OpenGL fonksiyonum. Bu fonksiyonda ekranda görünmesi istediğiniz bütün modelleri çağırabilirsiniz. Basit bir poligondan gelişmis bir oyun karakterine kadar... Böyle çalışıyor: İlk olarak renk ve depth buffer’ı temizlemelisiniz, sonra sahnenizi double(duble) buffer yaparak render ediyorsunuz. Double buffering, grafik sistemin kullandığı bir tektir. Pürüzsüz bir render yapmak için, iki renk buffer kullanarak çizerek genellikle söylenişi: ön renk buffer ve arka renk buffer. Double buffer ile sahneni (off-screen) back buffer’a render ediyorsunuz. Sahne render’ı bittikten sonra, arka buffer’ı ön buffer ile değiştiriyorsunuz. Bu buffering işlemi o kadar hızlı yapılıyor ki, kullanıcıdan gizli olarak yapılıyor. Double buffering tekniği genelde sahne direk ekrana render olurken ortaya çıkan küçük yanıp sönme ve titreşme problemini ortadan kaldırıyor. Herzaman ilk olarak sahneyi temizlemelisiniz. Bu boyadığın karenin üzerine yazmanı engeller. Eğer iki “katmanın değişmesi” fikri size hoş gelmedi ise, direk sahneye çiziliyor diye hayal edin, benim yaptığım gibi :) Şimdi nasıl çalıştığını öğrendiniz, pencere kodunu kafaya takmayın biz sizin için bu işlemi yaptık. Basit bir kitapmış gibi düşünün…

 

int DrawGLScene(GLvoid)      // Burası Bütün Çizimleri Yapacağımız Yer

{

    // Ekran Ve Depth Buffer’ı Temizle

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Şimdiki Modelview Matrix’i Resetle

    glLoadIdentity();

       

    // Kodu Buraya Yerleştir!

 

    return TRUE;                      // Durma

}

 

7# Sonraki kod bölümünü tam çıkmadan önce aranıyor. KillGLWindow’un amacı Rendering Context’i serbest bırakmak için (realease), Device Context ve sonunda window handler. NeHe birçok hata arayanlar ekledi bu fonksiyona. Eğer program pencerenin herhangi bir parçasını yok edemez ise, üzerinde hatayı tanımlayan bir mesaj kutusu belirerek, hataları bulmayı çok daha kolaylaştırıp, manuel debugging yapabilmek için.

   

GLvoid KillGLWindow(GLvoid)             // Uygun Olarak Pencereyi Öldür

{

    if (fullscreen)                   //Tam Ekran Modunda mıyız?            {

        ChangeDisplaySettings(NULL,0); // Masaüstüne Geri Git

        ShowCursor(TRUE);              // Fare Simgesini Göster

       

    if (hRC)                          //Rendering Context’imiz Var mı?    {

      if (!wglMakeCurrent(NULL,NULL))    // DC ve RC’yi serbest Bırakabilir miyiz?     

        {

               MessageBox(NULL,"Dc ve RC Serbest Bırakılamadı.",

               "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

        }

 

        if (!wglDeleteContext(hRC))           //RC Silinebilir mi?

        {

        MessageBox(NULL,"Rendering Context Serbest Bırakılamadı.",

               "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

        }

        hRC=NULL;                      // RC’yi Geçersiz Yap (Null)

    }

 

    if (hDC && !ReleaseDC(hWnd,hDC))  // DC’yi Serbest Bırakabilir miyiz?

    {

        MessageBox(NULL,"Release Device Context Failed.",

        "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

        hDC=NULL;                           // DC’yi Geçersiz Yap (Null)

    }

 

    if (hWnd && !DestroyWindow(hWnd)) // Pencereyi Yok Edebilir miyiz?

    {

        MessageBox(NULL,"Could Not Release hWnd.",

        "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

        hWnd=NULL;                     //hWnd’yi Geçersiz Yap (Null)

    }

 

    if (!UnregisterClass("OpenGL",hInstance)) //Class’ı Unregister Yapabilir miyiz?                                                        {

        MessageBox(NULL,"Class Unregister Yapılamadı.",

        "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

        hInstance=NULL;                // hInstance’i Geçersiz Yap               }

}


8# Bu UZUN fonksiyon OpenGL Win32 pencere yaratır. Genel olarak Win32 penceresi yaparak başlar, bize tam ekran istiyor muyuz diye sorar ve bizim istediğimiz OpenGL pencere değerlerini yerleştirir. Sonunda eğer herşey sorunsuz devam etti ise InitGL’yi cağırır, bizim kurulum fonksiyonumuz.

 

İlk gördüğünüz değişken PixelFormat’tır. Fonksiyonun ileriki zamanlarında Windows’a bizim istediğimiz pixel format’ı “soracağız”, Windows’un bizim için bulduğu mod’un numarası PixelFormat’ta değişken olarak saklanacaktır.

 

WNDCLASS wc objesi bizim Window Class gövdesini tutmayı sağlayacak. Window Class gövdesi penceremiz hakkında bilgi tutar. Class’ın belirli alanlarını değiştirerek penceremizin nasıl görüneceğini ve nasıl davranacağını değiştirebiliriz. Gördüğünüz her pencerenin kendi Window Class’ı vardır. Pencere yaratmadan önce, ilk olarak bir class kaydolmalisiniz pencereniz icin (register).

 

dwExStyle ve dwStyle, Extended ve Normal pencere sitilinin bilgilerini tutar. Sitilleri saklamak için değişkenler kullanılabilir ki sitilleri değiştirebiliriz istediğimiz tip pencereye göre (Popup penceresi için tam ekran veya kenarlı pencere windowed mod için).

 

Aşağıdaki 5 sıra kod dikdörtgenin sol-üst değerlerini, ve sağ-alt değerlerini tutar. Bu değerleri pencere boyutunu değiştirmeye kullanabiliriz ki çizgimiz çözünürlük tam penceremizin istediğimiz boyutu olsun. Eger 640x480 pencere yaparsak pencerenin kenarları çözünürlüğümüzden biraz alırlar.

 

Şimdi fulscreen flag’ine yerleştireceğimiz değerlere geliyoruz. Wc window class object kullanarak bazı özellikleri belirlemeye başlamadan önce. Fare simgesinin değerlerini, uygulama ikonları ve message handler’ımızı yükleriz. Bundan sonra window class’ımızı RegisterClass ile register ederiz…

 

Sonraki fonksiyon bölümü tam ekrana dönüşüm ile ilgili olacak. Birkaç dikkate alınacak şey var tam ekrana dönüşümde. Tam ekranda kullanılacak en ve boy planladığınız pencerenin eniyle ve boyuyla aynı olsun, ve en önemlisi tam ekranı ayarlayınız pencere yaratmadan önce. Bu kodda eni ve boyu kafanıza takmayınız, tam ekran ve normal ekranın boyutları aynı ayarlanmalı istenildiği gibi.

 

Bu fonksiyon hem de tam ekrana dönmeden önceki boyu kayıtlamali. Bu sayede aynı çözünürlükte başlarsınız kurulumu kapatınca önceden yaptığınız gibi… Bazı sinir bozucu programlar bunu yapmayı unutur, çözünürlüğünüzü değiştirir, ve sonrasında manuel olarak değiştirmeniz gerekir…

 

İstediğimiz görüntü modunu ayarladıktan sonra AdjustWindowRectEx’i kullanırız dikdörtgenin değerleri için ve CreatWindowEx’i de penceremizi istediğimiz boyut ve özellikleriyle kurması için. Eğer fonksiyon pencereyi doğru kuramazsa, pencereyi yok edip programdan çıkar.

 

Gelecek olan kod ise Pixel Format’ı anlatıyor. OpenGL ve double buffering’i destekleyen bir format seçiyoruz, beraberinde RGBA(kırmızı, yeşil,mavi, alpha channel). Bir pixel format ararız bizim seçtiğimize uyan (16bit, 24bit, 32bit). Sonunda 16bit Z-Buffer seçiyoruz. Geriye kalan parametreler ya kullanılmıyor ya da önemli değiller (stencil buffer ve (yavas) accumulation buffer bir yana). Penceremizi yarattıktan sonra hata aramaları yapması herşey yolunda ve planda gittimi bakması uygundur.

 

Bakarız eğer:

-device context alamıyorsak

-doğru pixel format bulamıyorsak

-pixel formatı yerleştiremezsek

-rendering context alamıyorsak

-rendering context’i aktif edemiyorsak

 

Eğer herşey planlandığı gibi gittiyse, ve bizim OpenGL Win32 penceremiz düzgün bir şekilde yaratıldı ise yeni pencereyi göstermemiz lazım, ön plan penceresi yapmamiz lazım (higher priority) ondan sonra odağı (focus) ayarlamamız gerekiyor. Ondan sonra ReSizeGLScene’i arayabiliriz ve o da ekran eni ve boyunu yeni OpenGL ekranına görüş açısı ile verebilir. SONUNDA OpenGL setup fonksiyonunu (InitGL) arama vakti geldi…

 

BOOL CreateGLWindow(char* title, int width, int height,

                   int bits, bool fullscreenflag)

{

    //ilk olarak standart Win32 pencere yaratımı      

GLuint  PixelFormat;

    WNDCLASS   wc;

    DWORD              dwExStyle;    

    DWORD              dwStyle;      

    RECT               WindowRect;

    WindowRect.left=(long)0;

    WindowRect.right=(long)width;

    WindowRect.top=(long)0;          

    WindowRect.bottom=(long)height;  

 

    // tam ekran değişkeni (variable)

    fullscreen=fullscreenflag;

 

    hInstance          = GetModuleHandle(NULL);

    wc.style           = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

    wc.lpfnWndProc             = (WNDPROC) WndProc;

    wc.cbClsExtra              = 0;

    wc.cbWndExtra              = 0;

    wc.hInstance               = hInstance;

    wc.hIcon           = LoadIcon(NULL, IDI_WINLOGO);

    wc.hCursor         = LoadCursor(NULL, IDC_ARROW);

    wc.hbrBackground   = NULL;               

    wc.lpszMenuName    = NULL;       

    wc.lpszClassName   = "OpenGL";   

 

    // Window class kaydı (register)

    if (!RegisterClass(&wc))         

    {

        MessageBox(NULL,"Window Class Kaydolunamadı.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;                 

    }

 

    // Eğer tam ekran bayrağı (flag) seçilmiş ise

    if (fullscreen)   

    {

        DEVMODE dmScreenSettings;

        memset(&dmScreenSettings,0,sizeof(dmScreenSettings));

        dmScreenSettings.dmSize=sizeof(dmScreenSettings);

        dmScreenSettings.dmPelsWidth   = width;

        dmScreenSettings.dmPelsHeight  = height;

        dmScreenSettings.dmBitsPerPel  = bits;

        dmScreenSettings.dmFields=DM_BITSPERPEL|

                               DM_PELSWIDTH | DM_PELSHEIGHT;

 

        //Selected modu seçmeye caliş ve sonuçları gör.

        if (ChangeDisplaySettings(&dmScreenSettings,

               CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)

        {

               if (MessageBox(NULL,"Tam ekran İsteğiniz Gerçekleştirilemedi Video Kartınız Desteklemiyor Yerine Pencere Modunu Kullan?",

               "OPENGL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)

               {

                       fullscreen=FALSE;

               }

               else

               {

                       MessageBox(NULL,"Program Şimdi Kapanacak.",

                       "ERROR",MB_OK|MB_ICONSTOP);

                       return FALSE;

               }

        }

    }

 

    if (fullscreen)   

    {

        dwExStyle=WS_EX_APPWINDOW;

        dwStyle=WS_POPUP;     

        ShowCursor(FALSE);    

    }

    else

    {

        dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

        dwStyle=WS_OVERLAPPEDWINDOW;  

    }

 

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

 

    //Pencereyi Yarat

    if (!(hWnd=CreateWindowEx( dwExStyle,    

                               "OpenGL",     

                               title,        

                               dwStyle |             

                               WS_CLIPSIBLINGS |     

                               WS_CLIPCHILDREN,

                               0, 0,                         

                               WindowRect.right-WindowRect.left,

                               WindowRect.bottom-WindowRect.top,

                               NULL,                 

                               NULL,         

                               hInstance,            

                               NULL)))

   

        KillGLWindow();        //Display’i Resetle    MessageBox(NULL,"Pencere Yaratma Sorunu.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;                 

    }

 

    // Pencereye nasıl istediğimizi söyle...

    static     PIXELFORMATDESCRIPTOR pfd=

    {

        sizeof(PIXELFORMATDESCRIPTOR),

        1,                     // Versiyon Numarası

        PFD_DRAW_TO_WINDOW |   // Format Pencereyi Desteklemeli

        PFD_SUPPORT_OPENGL |   // Format Open Desteklemeli

        PDF_DOUBLEBUFFER,      // Double Buffering yapmak

        PFD_TYPE_RGBA,         // RGBA Formatı İstemek (request)

        bits,                  // Renk Depth Seçimi

        0, 0, 0, 0, 0, 0,      // Color Bits Önemsiz (ignored)

        0,                     // Alpha Buffer Yok

        0,                     // Shift Bit Önemsiz (ignored)

        0,                     // Accumulation Buffer Yok

        0, 0, 0, 0,            // Accumulation Bits Önemsiz (ignored)

        16,                    // 16Bit Z-Buffer (Depth Buffer) 

        0,                     // Stencil Buffer Yok

        0,                     // Auxiliary Buffer Yok

        PFD_MAIN_PLANE,        // Ana Çizim Katmanı

        0,                     // Reserved

        0, 0, 0                // Katman Maskesi Önemsiz (ignored)

    };

 

    //Device Context Alındı mı?

    if (!(hDC=GetDC(hWnd)))   

    {

        KillGLWindow();        //Görüntüyü Resetle MessageBox(NULL,"GL Device Context Yaratılamadı.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

 

    // Windows Es Pixel Format Bulabildi mi?

    if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) 

    {

        KillGLWindow();        //Görüntüyü Resetle MessageBox(NULL,"Uygun PixelFormat Bulunulamadı.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

    //Pixel Format’ı Yerleştirebiliyor muyuz?

    if(!SetPixelFormat(hDC,PixelFormat,&pfd))       

    {

        KillGLWindow();        //Görüntüyü Resetle    MessageBox(NULL,"PixelFormat Yerleştirilemedi.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

 

    // Rendering Context Alabiliyor muyuz?

   if (!(hRC=wglCreateContext(hDC)))

    {

        KillGLWindow();        // Görüntüyü Resetle

        MessageBox(NULL,"GL Rendering Context Yaratılamadı.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

 

    // Rendering Context’i Aktif Hale Getirmek

    if(!wglMakeCurrent(hDC,hRC))     

    {

        KillGLWindow();        //Görüntüyü Resetle     MessageBox(NULL,"GL Rendering Context Aktif Hale Getirilemedi.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

 

    ShowWindow(hWnd,SW_SHOW);  // Pencereyi Göster

    SetForegroundWindow(hWnd); // Biraz Yükseltilmiş Öncelik (priority)   SetFocus(hWnd);           //Pencerenin Odağını Yerleştirir    ReSizeGLScene(width, height);    // GL Görüş Açısını Yerleştirmek

 

    // Yeni Kurulan Penceremizi Başlangıç Durumuna Getir (initialize)    if (!InitGL())

    {

        KillGLWindow();        //Görüntüyü Resetle    MessageBox(NULL,"Başlagıç Durumuna Getirilemedi.",

        "ERROR",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;          // Return FALSE

    }

 

    return TRUE;                      // Başarı

}


9# Bu bizim windows message handler WndProc (windows procedure). Penceremize gelen bütün mesajları ele alır  fare oynaması, tuşa basmak, kurulum kapanması vb. Aşağıdaki kod standart bir message döngüsü için: Bu emirler aranıyor WM_ACTIVE // eğer pencere aktif iseWM_SYSCOMMAND // sistem emirini keserseWM_CLOSE // kapat pencere emirindeWM_KEYDOWN // eğer tuş basılı iseWM_KEYUP // tuş bırakıldı iseWM_SIZE // eğer pencere yeniden boyutlandırılmış ise


LRESULT CALLBACK WndProc(      HWND hWnd,     // Pencerenin Ele Alınımı

                       UINT    uMsg,   //Pencerenin Mesajı

                       WPARAM  wParam,  //İlave Mesaj Bilgisi

                       LPARAM  lParam) // İlave Mesaj Bilgisi

{

        switch (uMsg)                  //Windows Mesajlarına Bak

        {

               case WM_ACTIVATE:      //Windows Aktif Hale Getir Mesajına Bak

               {

                       if (!HIWORD(wParam))//Küçültülmüş Duruma Bak 

                               active=TRUE;//Program Aktif                  

}

                       else

                       {

                               active=FALSE;//Program Aktif Değil                    

}

 

                       return 0;      // Mesaj Döngüsüne Geri Don

               }

 

        case WM_SYSCOMMAND:       //Sistem Emirlerini Kesiş (intercept)     

        {

                       switch (wParam) //Sistem Aramalarına bak                      

{

                               //Ekran Koruyucusu Başlamaya Calışıyor?

                               case SC_SCREENSAVE:   

                           //Monitör Güç Tasarrufuna Girmeye Çalışıyor?

                               case SC_MONITORPOWER:

                               return 0;      // Olmasını Engelle

                       }

                       break;                 // Çık

               }

 

               case WM_CLOSE: // Çıkış Messajı Aldık mı?

               {

                       PostQuitMessage(0);//Çıkış Mesajı Yolla

                       return 0;              // Geriye Atla

               }

 

               case WM_KEYDOWN:  // Bir Tuş Şu an Basılıyor mu?

               {

                       keys[wParam] = TRUE;// If So, Mark It As TRUE

                       return 0;              // Geriye Atla

               }

 

               case WM_KEYUP:         // Bir Tuş Bırakıldı mı?

               {

                       keys[wParam] = FALSE;// If So, Mark It As FALSE

                       return 0;                      // Geriye Atla

               }

 

               case WM_SIZE:   //OpenGL Penceresini Yeniden Boyutlandır    

        {

                       // LoWord=En, HiWord=Boy

                       ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));

                       return 0;                      // Geriye Atla

               }

        }

 

        // DefWindowProc’a Ellenmemiş Bütün Mesajları Yolla

        return DefWindowProc(hWnd,uMsg,wParam,lParam);

}


10# Sonunda Win32’den aranan fonksiyona bakıyoruz Winmain. Gördüğünüz gibi bu fonksiyon 2 değişken belirleyerek başlar. İlk değer msg mesaj döngüsü içindir. İkincisi ise bir boolean, mesaj döngüsünden çıkmak için. Ondan sonra bir mesaj kutusu belirip bize hangi ekran modu kullancağımızı sorar. Fonksiyonumuz sonra da CreateGLWindow’u arar ve istenilen boyutta ve tam ekran değişkeni ile. Pencere yaratıldıktan sonra bu fonksiyon döngüye dönüşür. Bu mesaj döngüss Esc ya da pencere çıkış düğmesine basılmadığı sürece devam eder. Eğer bu fonksiyonu araştırıp calışırsanız bir süre, F1’e basarak tam ekrandan pencere moduna geçilebilineceğini göreceksiniz.


int WINAPI WinMain( HINSTANCE hInstance,      // Misal

                 HINSTANCE hPrevInstance,     // Önceki Misal

                 LPSTR lpCmdLine,     // Emir Dizisi Parametreleri

                 int nCmdShow)        // Pencere Göster

{

        MSG     msg;                   // Windows Mesaj Structure

        BOOL    done=FALSE;    // Döngüden Çıkmak İcin Bool Değişken

 

        //Kullanıcıya Hangi ekran Modunu Kullandıklarını Sorar

        if (MessageBox(NULL,"Tam ekranda Calışmak İster misiniz?",

        "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)

        {

               fullscreen=FALSE;      //Pencere Modu }

 

        // OpenGL Penceremizi Yaratalım

        if (!CreateGLWindow("APRON TUTORIALS",640,480,16,fullscreen))

        {

               return 0;      // Eğer Pencere Yaratılmadı İse Çık

        }                                      

 

        while(!done)           // done=FALSE varken çalışan döngü

        {

               //Bekleyen Bir Mesaj mı Var?

               if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))

               {

                       // Çık Mesajı Aldık mı?

                       if (msg.message==WM_QUIT)

                       {

                               done=TRUE;// If So done=TRUE

                       }

                       else    // Yoksa, Pencere Mesajları ileİlgilen

                       {

                               // Mesajı Cevir (translate)

                               TranslateMessage(&msg);

                               // Mesajı Sal

                               DispatchMessage(&msg);

                       }

               }

               else                   // Eğer Hiç Mesaj Yok İse             {

                       // Sahneyi Çiz.

                       //Aktif mi?, Çık Emri Alındı mı?

                       if ((active && !DrawGLScene()) || keys[VK_ESCAPE])

                       {

                              // Esc ya da DrawGLScene Çık Sinyali Aldı                             done=TRUE;

                       }

                       else           //Çıkmaya Zaman Değil mi?, Ekranı Güncelle                      {

                               // Bufferları Değiştir (Double Buffering)

                               SwapBuffers(hDC);

                       }

 

                       if (keys[VK_F1])       // F1’mi Basılıyor?

                       {

                               keys[VK_F1]=FALSE;// If So Make Key FALSE

                               KillGLWindow(); // Şimdiki Penceremizi Öldur

                               // Tam Ekrandan Pencere Moduna Geçiş

                               fullscreen=!fullscreen;

                               // OpenGL Pencerimizi Yeniden Yarat

                               if (!CreateGLWindow("APRON TUTORIALS",

                               640,480,16,fullscreen))

                               {

                                      //Çık Eğer Yaratılamadı İse                                   return 0;

                               }

                       }

               }

        }

 

        // Shutdown

        KillGLWindow();        //Pencereyi Öldur

        return (msg.wParam);   // Programdan Çik

}


Bukadar! Şimdi nefes albilirsiniz :) Bir pencere için bu kadar kod çok fazla diye düşünebilirsiniz. Ama kullandıkça alışırsınız. Yüklemeyi deneyip derleyebilirsiniz isterseniz. Eğer kodu kısaltmak isterseniz hata aramalarını silebilirsiniz, ama önermem. Pek çok OpenGL programcıları ilk olarak kendileri bir pencere yaratmamıştır, ama tavsiyem birkaç kez üzerinden geçin. İleriki OpenGL kurulumlarında kullanabilirsiniz. Bunu öğrenin sonra sonraki ve daha kolay olan eğitsellere geçin.


Editör Notu: Bu benim için bir ilkti umarım beğenmişsinizdir. Eğer hatam var ise lütfen söyleyin :) Yaklaşık 5 gün sürdü çevirmek. İyi Gunler.


KAYNAK  


Çeviren: Kağan AKBAŞ - Görsel Tasarım – Çeviri Editörü

Son Güncelleme ( Pazar, 20 Ocak 2008 17:47 )
  Yorum yok.
Yorum ekle. (0 yorum)

 

OyunGelistirici.net - Türk Oyun Yapımcılarının Buluşma Noktası

Bu sitede yazılan tüm yazıların hakları yazarlarına aittir. İzin alınmadan yayınlanamaz.

Bu sitede Firefox kullanmanız önerilir. En az 1024 x 768 masaüstü çözünürlüğü tavsiye edilir.