Ana Menü
· Ana Sayfa
· Dosyalar
· Dökümanlar
· Forum
· Günün Resmi
· Haber Arşivi
· WWW Linkleri
· Üye Listesi

     Forumlar

 strncpy ve strncpy_s
 Konu adi : Borland c++ Builder ile Amiral Batti
 Rady10 - YerliOyun
 Kabusta Kaybolmak
 Konsol da programı bekletmek
 Oyun programlama icin hangi programlama dilli ?
 flash! şanlıurfa bilgisayar oyununda(no rapid)
 Sevgilim Olur musun?
 Directx'e başlamak isteyenler bi bakın
 PSP programlama
 Flash tan php
 Bilgisyr oyunu yapmam için üniverstde hangi bölüme girmeliym
 www.arshiv.gen.ms
 Cimg.h ilgilenenler icin
 müttefik oyunu

Konu Disi
 Emraah
 Yeni sitemiz açıldı
 Kalp krizi durumunda ne yapılmalı?
 Oyun sektöründe hangi görevde çalışmak isterdiniz?
 Takım arkadaşı sorunu
 msn de renklı nıck
 pc hata veriyor ! YARDIM!!
 Gülmek isteyenler Buraya
 İnanılmaz hl 2 modu görüntüsü
 Computer Languages History

[ Forumlara Git ]


WIN32 API Kullanarak OpenGL Programlamaya Giriş

(1937 kelime)
(1405 okuma)   Yazdırılabilir Sayfa




WIN32 API Kullanarak OpenGL Programlamaya Giriş:


//Bu programda windowsta bir opengl programı yaratmayı ve ekrana basit bir çizim yapmayı
//işleyeceğiz :) Anlatımları mümkün olduğunca yeni başlayanlara yönelik hazırlamaya çalıştım.
//Yine de anlayabilmek için programlamadan orta derecede haberdar olmanız gerek.


#define WIN32_LEAN_AND_MEAN
//Bunu yazarak windows headerlarındaki bize yaramayacak fazlalıkları ayırıyoruz.Böylece
//programımızın *.exe si daha az yer kaplıyor.


#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_DEPTH 32
//en boy ve renk derinligi için tanımlamalar

#include <windows.h>
//Windows fonksiyon ve tanımlarının olduğu dosyayı ekliyoruz.

#include <gl\gl.h>
#include <gl\glu.h>
//OpenGL tanımlamalarını ve fonksiyonları kullanmak için bu dosyaları ekliyoruz.

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
//OpenGL kütüphanelerini ekliyoruz.Bunu Project\Settings Link kısmına gidipte yapabilirdik.

HDC g_hdc;
//device context(programın sonunda açıklama yapmaya çalıştım ;))

HGLRC g_hrc;
//rendering context yine çizim için gerekli

float aci=0.0f;
//ekranda bir üçgeni döndürmek için kullanacağız


LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
//bu fonksiyon windows'un programa yolladığı mesajları kontrol etmemizi sağlıyor.
//bu mesajlar;boy değiştirme,kapanma,hareket etme gibi şeyler.
//parametreler (hwnd - penceremizi belirtiyor,iMsg mesajı,wParam ve lParam gelen mesaj hakkında
//ek bilgi içeriyor.)



int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nShowCmd)
//dos uygulamalarındaki main() windows programlarında WinMain'e dönüşüyor.Bu fonksiyon geriye
//int döndürüyor.int'ten sonra gelen "WINAPI" bu fonksiyonun programın başlangıç noktası olduğunu belirtiyor.
//Şimdi parametrelere gelelim...
//hInstance     - programın o anı için bilgiler tutuyor.
//hPrevInstance - programın bir önceki anı için bilgiler tutuyor(O_o).Bu tüm win32 programlarında NULL
//                  yani sıfır işimize yaramayacak.
//lpCmdLine     - program çalıştırılırken komut satırında exe nin yanına yazılanlar bu değişkene
//                  gönderiliyor.Örnek : "ilkprog.exe deneme 1" yazarsak lpCmdLine "deneme 1" olur.
//nShowCmd      - program ilk çalıştırıldığında penceremizin nasıl gösterilceğini belirten değişken.

{
    //evet programımız başladı.şimdi yapmamız gereken bir pencere yaratmak.
    //bunu yapmak için WNDCLASSEX adındaki yapıyı kullanacağız.Bu yapının içini doldurup,
    //windows'a register edip bu yapıdaki özelliklere sahip bir pencere yaratabiliriz.

    WNDCLASSEX winclass;
    ///windows class(sınıf)

    HWND hwnd;
    //hwnd - yaratacağımız pencereyi kullanmamızı saglayacak değişken.(pencereyi yarattıktan sonra daha
    //iyi göreceksiniz.)

    MSG msg;
    //windows'un programımıza gönderebileceği tonlarca mesaj var.Bu mesajları bu değişkenle kontrol
    //edeceğiz.


    bool bBitti;
    //ve son olarak programın sonlanıp sonlanmadığını kontrol etmemizi sağlayacak değişken.

    //şimdi winclass'ın içini dolduracağız.Bu biraz uzun gelebilir ve burdaki her şey anlaşılamayabilir.
    //ama burda yazılanlar her programda nerdeyse aynı yani ilerde bunları bir fonksiyona koyup bir daha
    //yüzüne pek bakmadan kullanabilirsiniz.
    //Neyse niye uzattım ki bu kadar işte winclass... :)

    winclass.cbSize=sizeof(WNDCLASSEX);                    //yapının boyutunu belirtiyoruz
    winclass.style=CS_HREDRAW|CS_VREDRAW;                //pencere dikey veya yatayda değişikliğe uğrarsa
                                                        //tekrar çizilmesini istiyoruz
    winclass.lpfnWndProc=WndProc;                        //windows mesajlarını halledicek fonksiyonumuz
    winclass.cbClsExtra=0;                                //bu ikisi hep sıfır
    winclass.cbWndExtra=0;                                //^^^^^^^^^^
    winclass.hInstance=hInstance;                        //WinMain'deki hInstance'ı hatırladınız mı işte burda
                                                        //kullanıyoruz.
    winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);        //program ikonunu yüklüyoruz.(alt+tab yapınca çıkan)
    winclass.hCursor=LoadCursor(NULL,IDC_ARROW);        //Cursor  olarak ok yüklüyoruz.
    winclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);    //background'u beyaza boyuyoruz.
    winclass.lpszMenuName=NULL;                            //menümüz yok.
    winclass.lpszClassName="patlican";                    //class ismi.buna istediğiniz ismi verin :)
    winclass.hIconSm=LoadIcon(NULL,IDI_WINLOGO);        //küçük ikon (pencerenin sol üst köşesinde çıkan)

    //evet winclass'ı doldurduk şimdi bunu kayıt etmemiz lazım bunu aşağıdaki gibi yapıyoruz.
    //eğer register ederken bi sorun çıkarsa programı bitiriyoruz.Ama genelde sorun çıkmaz :P

    if(RegisterClassEx(&winclass)==NULL)
        return 0;


    //kayıt işi bitti şimdi penceremizi yaratabiliriz.Bunun için CreateWindowEx(); fonksiyonunu kullanıyoruz.
    //bu fonksiyonunda birçok parametresi var.bu fonksiyon geriye,yarattığı pencereyi tanımlayan bir değer
    //gönderiyor bunu hwnd ye koyuyoruz böylece yaratılan pencereyi kontrol edebiliriz.

    hwnd = CreateWindowEx(NULL,                                //still için extra bilgi yok
                          "patlican",                        //class ismimiz yukardakiyle aynı olmalı
                          "İlk OpenGL Programımız",            //programın tepesinde yazan isim
                          WS_OVERLAPPEDWINDOW,                //pencerenin stili,ufaltma kapama buttonları var cervesi var vs.
                          100,100,                            //pencerenin sol üst köşesinin koordinatları
                          SCREEN_WIDTH,SCREEN_HEIGHT,        //pencerenin genişliği ve boyu
                          NULL,                                //pencerenin parent'ı yok yani ona sahip bir üst pencere yok
                          NULL,                                //pencerenin menüsü yok.
                          hInstance,                        //hInstance'ı burda da yazıyoruz.
                          NULL);                            //extra parametre yok
    //şimdi pencerenin yaratılmasında hata oluşup oluşmadığını kontrol ediyoruz.Eğer hata oluşmuşsa hwnd
    //NULL olur.Bir hata varsa prorgramı bitiriyoruz.

    if(hwnd==NULL)
        return 0;

    //penceremizi yarattıktan sonra artık opengl ile alakalı işlere başlayabiliriz.ilk olarak
    //pixel format oluşturacagız.

    PIXELFORMATDESCRIPTOR pfd;
    //pixel format yapısı

    //şimdi pixel format yapısını dolduracağız

    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);        //yapının boyutu
    pfd.nVersion = 1;                                //bunun her zaman 1 olması lazım
    pfd.dwFlags = PFD_DRAW_TO_WINDOW                //pencereye cizimi,
                 | PFD_SUPPORT_OPENGL                //opengl'i
                 | PFD_SUPPORT_GDI                    //gdi cizimlerini
                 | PFD_DOUBLEBUFFER;                //ve double bufferı destekleyen bir pixel format
    pfd.dwLayerMask = PFD_MAIN_PLANE;                //bu dikkate alınmıyor.
    pfd.iPixelType = PFD_TYPE_RGBA;                    //renk olarak kırmızı yesil mavi ve
                                                    //alpha(şeffalık için) istiyoruz
    pfd.cColorBits = SCREEN_DEPTH;                    //renk derinligi
    pfd.cDepthBits = 16;                            //bu z bufferın derinligi
    pfd.cAccumBits = 0;                                //bunlar şu an gerekli diil
    pfd.cStencilBits = 0;                            //stencil buffer da istemiyoruz

    //yapıyı doldurduk. :D

    g_hdc=GetDC(hwnd);
    //penceremizin "device context"ini alıyoruz.bu çizim yapmamız için gerekli.

    int nPixelFormat;
    if ((nPixelFormat=ChoosePixelFormat(g_hdc,&pfd))==FALSE )
       //ChoosePixelFormat fonksiyonu yukarda belirtigimiz özelliklere en iyi uyan pixel formatı seçer.
    //ve geri bu pixel formatı belirten bir sayi döndürür.

    {
        //hata olusursa bir mesaj kutusu ile haberdar ediyoruz kullanıcıyı.ve programı bitiriyoruz.
        MessageBox(NULL, "Pixel Format seçme başarısız!", "Hata", MB_OK);
        PostQuitMessage(0);
    }

    if (SetPixelFormat(g_hdc, nPixelFormat, &pfd) == FALSE)
    //seçilen pixel formatı kullanmak için bu fonksiyonu kullanıyoruz.
    {
        //yine bir uyarı mesajı ve programı bitiriyoruz.
        MessageBox(NULL, "SetPixelFormat başarısız!", "Hata", MB_OK);
        PostQuitMessage(0);

    }


    g_hrc=wglCreateContext(g_hdc);
    //son olarak "rendering context"i yaratıyoruz
    wglMakeCurrent(g_hdc,g_hrc);
    //ve g_hdc ye seçiyoruz.böylece artık g_hdc'yi kullanarak çizim yapabiliriz."rendering context"i
    //oluşturmadan önce pixel formatı yaratmalıyız.ayrıca bir kaç tane "rendering context"
    //yaratıp ayrı pencerelere render yapabiliriz.(harita editörlerinde olduğu gibi)
    //Ama bu konumuzun dışında :)


    ///Penceremizi gösterip update ediyoruz.hwnd işte burda ve pencere ile ilgili fonksiyonlarda kullanılıyor.
    ShowWindow(hwnd,nShowCmd);
    UpdateWindow(hwnd);

    bBitti=false;
    //programın bitmediğini belirten değişken

    while(bBitti==false)
    //burda döngümüze başlıyoruz.Programı bitirmek istedigimizde bBitti değişkenini true yapmamız yeterli.
    {
        //bu fonksiyon eğer bir mesaj varsa doğru olur.
        //Ve o mesajı 'PM_REMOVE' olduğu için mesaj kuyruğundan kaldırır.

        if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
        {
            //eger gönderilen mesaj çıkma mesajı ise yani kullanıcı pencereyi kapatmak istemişse programı
            //bitiriyoruz.

            if (msg.message == WM_QUIT)
                bBitti = true;
            //virtual key kodlarını character kodlarına çeviriyor gerekli :)
            TranslateMessage(&msg);
            //mesajı windos'a geri yolluyor.
            DispatchMessage(&msg);
        }
        //evet programızın en önemli kısmı burası.Buranın dışında yaptığımız herşey her programımızda neredeyse
        //aynı kalıcak.Burda ekrana bir üçgen cizip döndüreceğiz.En azında OpenGL ile birşey çizmiş olucaz bu
        //kadar koddan sonra :)


        //****rendering
        //önce ekranı ve depth bufferı temizliyoruz.


        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        //sonra modelview matrisi birim matrise eşitliyoruz.yani her frame(kare)de herşey ilk haline dönüyor.
        glLoadIdentity();
        //kamera her frame basında 0,0,0 da olduğu için 5 birim geri hareket ediyoruz
        //böylece ne çizdiğimizi göreceğiz.Bunu yapmak yerine çizdigimiz objenin z degerini -5 yapabilirdik
        //ama ben geri hareket etmeyi tercih ettim :)
                    //X      //Y  //Z


        glTranslatef(0.0f,0.0f,-5.0f);
        //glRotatef belli bir açı kadar bir eksen etrafında dönme sağlıyor.
        glRotatef(aci,0.0f,0.0f,1.0f);
        //açıyı artırıyoruz böylece dönme sürekli oluyor
        aci+=0.5f;
        //eğer tam bir tur atmışsak baştan başlıyoruz
        if(aci>=360.0f) aci=0.0f;
        //evet OpenGL de birşey çizmeden önce glBegin(); ile ne çizeceğimizi belirtiyoruz.
        //biz burda GL_TRIANGLES yazdık şimdi opengl yazdığım üç noktayı birleştirip bir üçgen
        //yapacağını biliyor.

        glBegin(GL_TRIANGLES);
            //birinci nokta tam merkezde
            glVertex3f(0.0f,0.0f,0.0f);
            //ikincisi onun sağında
            glVertex3f(1.0f,0.0f,0.0f);
            //üçüncü nokta merkezdekinin üstünde
            glVertex3f(0.0f,1.0f,0.0f);
        //çizim bitti
        glEnd();
        //çizim yaparken noktaların koordinatlarını saat yönünün tersinde yazmak iyi bir alışkanlık.
        //ama mecbur diilsiniz tabi :)


        SwapBuffers(g_hdc);
        //SwapBuffers(); nedir yahu diyenler olabilir.
        //Hani pixel format yaratırken şöyle bişey yazmıştık PFD_DOUBLEBUFFER;
        //şimdi bizim çizim için iki tane alanımız var bunlardan biri ön yüzey digeri arka yüzey
        //kullanıcı sadece ön yüzü görüyor biz ise çizimlerimizi arka yüzeye yapıyoruz.
        //çizimleri bitirince arka yüzü bu komutla öne getiriyoruz ve kullanıcı ne çizdiğimizi görüyor.
        //bunun faydası görüntünün titremesini önlemsi.inanmayan arkadaşlar pixelformattan
        //PFD_DOUBLEBUFFER 'ı kaldırıp farkı görebilirler :]


    }
    //bu noktaya gelindiğinde program bitmek üzere.Ama programı bitirmeden önce yapmamız
    //gereken bir kaç sey daha var.Öncelikle yarattığımız pencereyi aşağıdaki basit fonksiyonla
    //yok ediyoruz hwnd'nin faydaları yine görülüyor.

    DestroyWindow(hwnd);
    //pencereyi yok ettikten sonra sıra winclass'a geliyor.Onu da verdigimiz adı ve hInstance'ı
    //kullanarak unregister ediyoruz

    UnregisterClass("patlican",hInstance);
    //son olarak msg ın wParam kısmını döndürüyoruz ve programımız bitiyor.
    return msg.wParam;
}
//bu bizim mesaj fonksiyonumuz windowstan gelen farklı mesajları burada kontrol ediceğiz.Bu
//programda sadece bir kaç mesaja bakıcaz.

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
{
    //pencerinin boyutları değiştiğinde kullanacağız.
    int  height,width;

    switch(iMsg)
    {
    //bu mesaj sadece bir kere pencere yaratıldığında gelir.Eğer sadece bir kez yapılmasını istediğiniz
    //şeyler varsa mesela pixel format yaratmak o kodu burayada yazabilirdik.

    case WM_CREATE:

        break;
    //bu mesaj pencerenin boyutları değiştigi zaman gelir.Burada ufak bir OpenGL ayarı yapıyoruz.
    //bunun nedeni pencere boyutları değiştiginde perspektifi tekrar hesaplamak.

    case WM_SIZE:
        width = LOWORD(lParam);
        height = HIWORD(lParam);
        //pencerenin yeni genişliği ve boyu lParam içinde.

        if (height==0)
        //aşagıda genişliği boya böleceğiz bu yüzden boyun sıfır olması bir sayının sıfıra
        //bölünmesi ihtimalini doğuruyor ki buna asla programlarımızda izin vermemeliyiz

        {
            height=1;
            //boyu 1 yapıyoruz böylece hiçbir zaman sıfır olmuyor.
        }

        glViewport(0,0,width,height);
        //viewport'u bütün pencere yapıyoruz istersek daha küçük bir alanda yapabiliriz.
        //bu alan çizim yapacağımız bölgeyi belirtiyor.


        glMatrixMode(GL_PROJECTION);
        // projeksiyon matrisini seciyoruz
        glLoadIdentity();
        // ve birim matrise eşitliyoruz

        gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, 1 ,150.0f);
        //perspective ayarı yapıyoruz.parametreler sırasıyla
        //FOV   - field of view,görüş alanı
        //ratio - width/height oranı objelerin nasıl göründüğümü etkiliyor.
        //near clipping plane - objelerin kameradan ne kadar yakında çizilmeyecegini belirtiyor.
        //                        kameraya 1 birimden yakın objeler çizilmeyecek
        //far clipping plane - objelerin kameradan ne kadar uzakta çizilmeyeceğini belirtiyor.
        //                        kameradan 150 birim ve daha uzaktaki objeler çizilmeyecek.


        glMatrixMode(GL_MODELVIEW);
        //tekrar model matrisine dönüyoruz
        glLoadIdentity();
        //ve birim matrise eşitliyoruz
        break;
        //bu iki mesaj pencere kapatılmaya ya da yok edilmeye çalışıldığında gelir.
        //PostQuitMessage(0); WM_QUIT mesajı gonderir ki bunu da yukardaki döngüde kontrol ediyoruz.
        //(PeekMessage'ın orda)
        //böylece program bitiyor.

        case WM_DESTROY:
        case WM_CLOSE:
            //Program bitmeden önce yarattığımız "rendering context"i seçip siliyoruz.
            wglMakeCurrent(NULL,NULL);
            wglDeleteContext(g_hrc);
            PostQuitMessage(0);
            break;

    }
    //bu fonksiyon butun mesajlar için normal yapılanları yapıyor.
    return (DefWindowProc(hwnd, iMsg, wParam, lParam));
}

////Notlar:
// Bu program Microsoft Visual C++ 6.0 ile yazılmıştır.
// Programın çalışması için opengl kütüphanelerinin bilgisayarınızda bulunması gerekli
// ayrıca yeni bir proje yaratırken win32 application seçmelisiniz.
//
//
// Bu baya uzun bir program gibi gözüküyor ama yorumlar olmadığı zaman o kadar da uzun diil.
// Kısaca şunları yaptık.
// 1.Pencere classı yaratıp doldurduk.Bunu kaydettik sonra bir pencere yaratık.
// 2.Ardından pencerenin "device context"ini alıp bunu pixel format yaratmak için kullandık.
// 3.Daha sonra wglCreateContext ile "rendering context"i  yaratıyoruz ve bunu "device context" e seçiyoruz.
//   Artık çizim yapabiliriz.
// 4.Çizimlerimizi yapıyoruz ve programı bitiriyoruz.
//
// Mesajlar - Windows tarafından programa gönderilen mesajlardır.Siz mouse ile programı kapatmaya çalışınca
// ya da pencerenin boyunu değiştirdeğinizde farklı mesajlar oluşur.Bu mesajlar oluştuğunda programınızın neler
// yapacağına karar verebilirsiniz.Bunu WndProc fonksiyonu ile sağlıyoruz.
//
// HDC - handle to device context.İlk duyduğumda ve gördügümde ben de ne olduğunu tam anlamamıştım.
// hdc çıktı yapmanızı sağlayan bi yapı bizim durumuzda bu çıktı ekrana oluyor ama bu printer ile
// ya da başka çıktı araçlarıyla da olabilir.
//
// HGLRC - "rendering context" HDC ile çizim yapmak için rendering context oluşturmamız gerekiyor.
// rendering context OpenGL ile çizim yapmayı sağlıyor.
//
// Evet ilk OpenGL programımız bitti.Bu programda yazılan herşeyi hemen anlamanız pek mümkün diil.
// Benim tavsiyem programla oynayıp orasını burası değiştirmeniz ve neler olduğunu görmeniz.Böylece
// çok daha kolay öğrenebilirsiniz.
//
//

Barış S. Uşaklı :: www.oyunyapimi.org :: 2003 ::
  

[ Geri Dön: OpenGL | Bölümler İndeksi ]




Web site powered by PHP-Nuke
Web site engine\'s code is Copyright © 2002 by PHP-Nuke. All Rights Reserved. PHP-Nuke is Free Software released under the GNU/GPL license.
Sayfa Üretimi: 0.040 Saniye