You are on page 1of 99

2.1 OpenGL nedir ?

OpenGL dediimiz ey, grafiksel donanma arayz olan bir yazlmdr.Bu arayz, imdiki aratrmalarma gre yaklak olarak 250 tane birbirinden farkl olan OpenGL komutlar ierir ( bu komutlarn yaklak 200 tanesi OpenGLe has olan ve kalan 50 tanesi ise OpenGL Utility Lbrary dediimiz ktphaneye aittir.) Bu komutlar kullanarak objeleri yaratabilir ve interaktif bir ekilde boyutlu uygulamalar salayan ilemleri gerekletirebilirsiniz. OpenGL, fakl donanm zelliklerine sahip platformlarda alabilen bir arayz olarak tasarlanan, yani donanmdan bamsz bir aratr. OpenGLin bu niteliini geekletirebilmek iin OpenGLde kullancnn dardan bilgi girmesini salayan aralar ve iletim sistemlerinde pencere ynetimini salayan komutlar yoktur. Bu yzden programc bulunduu platformu iyi tanmal ve kulland iletim sistemi komutlarn iyi bilmelidir. Ayn ey boyutlu nesneler iin de geerlidir.Yani sylemek istediim ey, OpenGLin boyutlu nesneler iin salayaca yksek seviyeli komutlar yoktur. Sizin yapmanz gereken ey OpenGLin salad ilkel ( primitive) geometrik nesneleri kullanarak istediiniz modelde iki veya boyutlu nesneleri yaratmanzdr. lkel nesneler olarak bahsettiim eyler nokta, izgi, poligon gibi objelerdir. Bu zellikleri salayabilen gelimi bir ktphane OpenGLin stne ina edilmitir. OpenGL Utility Library ( GLU ) quadric yzeyleri, NURBS erileri ve yzeyleri gibi bir ok zzellii salamaktadr. GLU, her OpenGL implementasyonunun bir gerekletirim standarddr.

2.2 Kk bir OpenGL kodu


OpenGL grafik sistemi ile bir ok ey yapabildiinizden dolay, bir OpenGL program karmak olabilir.Fakat, programn temel yaps basit olabilir. OpenGLin nasl

reder ileminde kontrol grevini salayan belirli durumlar ilklemek ve render edilecek olan nesneleri ise belirlemek OpenGLin grevleri arasnda yer alr. OpenGL koduna bakmadan nce, birka terimi incelemekte fayda var. Mesela biraz nce kullandm render kelimesinin anlam bilgisayarn modellerden yaratt resimleri ileme anlamna gelir. Bu modeller ve nesneler geometrik ilkel elemanlardan yaratlrlar ( poligonlar, izgiler ve noktalar). Sonu olarak retilen resim yani render edilmi olan resim ekrannzda izilmi olan pikselleri ierir. Pikselin anlam, donanm tarafndan ekrana koyulan en kk grnr elementtir. Piksellerle ilgili bilgiler, memorideki bitplaneler iinde dzenlenmitir. Bitplane bir memori blgesidir. Bu blge ekran zerindeki her bir piksel ile ilgili tek bitlik bilgi tutmaktadr.rnek olarak, bit herhangi bir pikselin nasl krmz renkte olup olamayaca ile ilgili bilgiyi tutar.Bitplanelerin kendileri ise bir framebuffer ierisinde organize olmutur.Bu framebuffer, ekran zerindeki piksellerin renk kontollerini ve younlukar ile ilgili ihtiya duyduu bilgileri tutmaktadr. Bir OpenGL kodunu genel yapsn incelersek, rnek 2-1, arka plan siyah olan beyaz renkli bir karenin render ediini Resim 2-1 de gstermektedir.

Resim 2-1

rnek 2-1
#include <istenile balk dosyalar> int main(int argc, char** argv) { Pencerelklemelemleri(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glBegin(GL_POLYGON); glVertex3f(0.25, 0.25, 0.0); glVertex3f(0.75, 0.25, 0.0); glVertex3f(0.75, 0.75, 0.0); glVertex3f(0.25, 0.75, 0.0); glEnd(); glFlush(); PencereyiGncelleVeKontrolleriYap(); return 0; }

main() fonksiyonun ilk satr, ekranda gzkecek olan pencere ile ilgili hazrlk ilemleri yapmaktadr. Pencerelklemelemleri() fonksiyonu, OpenGLe ait olamayan iletim sistemine has pencere sistemi ile ilgili rutinleri ieren bir yer tutucudur. Sonraki iki satr ise pencerenin arka plann siyah olarak temizleyen OpenGL komutlardr: glClearColor(), pencerenin hangi renk ile temizleneceini belirler ve glClear() komutu ise pencereyi temizler. glColor3f() komutu izilecek olan nesnenin rengini belirtir. Bu

rnek ierisinde izilmi olan karenin rengi beyaz olarak belirlenmitir.Bu noktadan itibaren tm nesneler bu komut tarafndan yeni bir renk ayarlamas olana kadar bu rengi kullanrlar. Sonraki OpenGL komutu glOrtho() dur. Bu komut pencerede nesne izilmeden nce, koordinat sistemini belirtir. glBegin() ve glEnd() komutlar tarafndan sarlm olan komutlar, izilecek nesneyi tanmlamaktadr. rnek ierisinde greceiniz gibi drt keli bir poligon izilmitir. Poligonu keleri, glVertex3f() komutlar tarafndan tanmlanmaktadr. glVertex3f() komutu koordinat sistemi ile alakal tane parametre almaktadr. Bu parametreler x, y ve z dir. Bu rnek ierisinde znin deeri 0 olarak belirlenmitir. Son olarak glFlush() komutu izim komutlarn altrr. PencereyiGncelleVeKontrolleriYap() rutini ise pencere ile ilgili gncellemeri yapmaktadr ve dier processler arasndaki mesaj al-veriini dinlemektedir. Aslnda rnek 2-1, basit olarak OpenGL komut yapsn vermektedir. Ayrntlara raporumun sonraki sayfalarnda deineceim.

2.3 OpenGL Komut Sentaks


rnek 2-1 de ki basit OpenGL programn incelediyseniz, her OpenGL komutunun nne gl n eki getirilmektedir. Ayn ekilde, tanmlanm OpenGL sabitleri de GL n eki kullanlmtr ( rnein GL_COLOR_BUFFER_BIT gibi). Dikkat edeceiniz gibi baz ekler de bu komutlara birer anlam katmak iin kullanlmlardr. ( rnein glColor3f() komutunun son eki olan 3f ). Yaratlm olan nesnenin o anki rengini belirleyen komutun yani glColor3f() komutunun Color parasna bakarak anlamak yeterlidir sanrm. Fakat, komutlarn farkl sayda argman almalarn salamak iin, farkl komutlar tanmlanmtr. Mesela glColor3f() komutunda aklnza taklan 3 says, bu komutun tane argman aldn bildirmektedir. Komutun f karakteri, alnacak olan parametrelerin float tipinde olmalar gerektiini anlatmaktadr. Aslnda ksacas, OpenGL komutlarn yazarken, fonksiyonlarn ar yklenmesi sz konusu deildir. Bunu dikkate almakta fayda var.

Baz OpenGL komutlar, sekiz farkl tipte argman almaktadr. Bir sonraki sayfadaki tablo, OpenGL in ISO C gerekletirimi iin belirlenmi veri tiplerini nek olarak tanmlamalar ile beraber kullanmn gstermektedir. Bu veri tiplerini programlama dilinde kullanmakta fayda var, nk kullanlacak olan komutlarn argman tipleri, programla dilinde kullanlan veri tipleri ile uyumayabilir. Bu yzden, OpenGL komutlarnn tanabilirlii sz konusu ise bu komutlar kullanmakta fayda var. Tablo 2-1 Komut nekleri ve Argman Veri Tipleri
ne Veri Tipi k B 8-bit integer 16-bit integer 32-bit integer 32-bit floating-point 64-bit floating point 8-bit unsigned integer 16-bit unsigned integer 32-bit unsigned integer C programlama dilinde Kullanlan Tipler signed char Short int veya long Float Double unsigned char unsigned short unsigned int veya unsigned long OpenGL Tip Tanm GLbyte GLshort GLint, GLsizei GLfloat, GLclampf GLdouble, GLclampf GLubyte, GLboolean GLushort GLuint, GLenum, GLbitfield

S F D Ub Us Ui

Aadaki iki komutu incelersek


glVertex2i(1, 3); glVertex2f(1.0, 3.0);

her iki komut ta ayn ileve sahiptir. Fakat ilki, vertexin koordinatlar argman olarak 32-bit integerlar ve die komut ise argman olarak float tipindedir.

Baz OpenGL komutlar, son ek olarak v karakterini alr. Bu karakter, programcya parametre olarak alnacak eyin bir vectr veya bir diziyi iaret eden bir iareti olduunu bildirir.Birok komutun parametre olarak vector alan veya almayan versiyonlar bulunmaktadr. Aadaki satrlar glColor*() komutunun vektrl ve vektrsz olarak parametre almn gstermektedir.
glColor3f(1.0, 0.0, 0.0); GLfloat color_array[] = {1.0, 0.0, 0.0}; glColor3fv(color_array);

Son olarak, OpenGL veri tipi olarak GLvoidi tanmlar. Bu veri tipi dizileri iaret eden pointerlar, argman olarak alan OpenGL komutlar iin kullanlmaktadr.

2.4 GLUT, OpenGL Hizmet Arac (OpenGL Utility ToolKit)


Bildiiniz gibi, render komutlarn OpenGL iermektedir, fakat bir pencere sistemiden ve bir iletim sisteminden bamsz olarak tasarlanmtr. Sonu olarak ne alan pencerelere ait, ne de klavye ve mause olaylarna ait komutlar iermemektedir. Penceresiz bir grafik program yazmak imkanszdr ve ok ilgi eken programlar dardan kullanc bilgisi alrlar veya iletim sisteminin ve pencere sisteminin hizmetlerinden yaralanrlar. GLUT ktphanesini kullanarak, pencere yaratma dardan bilgi alma gibi fonksiyonlar kolayca kullanabiliriz. Raporumun ileriki sayfalarnda Windows iletim sistemini pencere sistemi gerekletirimine deineceim. OpenGL in ne olduunu aklarken, OpenGLin basit ilkel nesneleri izebilecek komutlarla snrl olduunu sylemitim, fakat GLUT sayesinde karmak boyutlu nesnelerimizi kolaylkla yaratabiliriz.

2.5 Pencere Ynetimi


Pencere yaratabilmek iin gerekli olan be rutin yerine getirlmelidir. glutInit(int *argc, char** argv) fonksiyonu GLUT ilkler ve komut satr argmanlarn ilemektedir. Dier GLUT rutinlerinden nce bu komutun yazlmas zorunludur. glutInitDisplayMode(unsigned int mode) renk modunu belirlemektedir. Bu renk modu RGBA veya color-index mod olabilir. Ayrca pencerenin single veya double buffered olacan belirlersiniz. Eyer bir pencerenin RGBA ve double buffered modda olmasn istiyorsanz, bu fonksiyonu glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE) olarak armalsnz. glutInitWindowPosition(int x, int y) fonksiyonu grafik penceresinin sol-st kesini baza alarak, ekrandaki yerini belirler. glutInitWindowSize(int width, int height), pencerenizin bykln ayarlar. (piksel birimi olarak) int glutCreateWindow(char* string), OpenGL conteksli bir pencere yaratr. Yeni pencereye ait tek yani esiz bir sat dnderir. Not: glutMainLoop() arlana kadar pencere yaratlamaz.

2.6 Grnty Geri arma ( The Display Callback )


glutDisplayFunc(void (*func)(void)) fonksiyonu greceiniz ilk ve en nemli fonksiyon arma fonksiyonudur. Nezaman GLUT, pencerenizin ieriinin yeniden

gsterileceine ihtiya duyduunu belirlerse, glutDisplayFunc() tarafndan altrlacak fonksiyon arlr. Anlalaca gibi, glutDispalyFunc() a parametre olarak aktarlan bir pointer to function tipinde bir iaretidir. Bu nedenden tr, pencerenizi yeniden izmeniz iin gerekli grdnz rutinleri aracanz fonksiyon ierisine yani void (*func)(void) poiner to function ierisine koyun.

2.7 Renkli bir ken


Yapacanz en son ey ise glutMainLoop(void) fnksiyonun armak olacaktr. Bunu sayesinde yarattnz pencere ekranda gsterilir. Bu fonksiyon GLUT olay ilem dngsne (the GLUT even processing loop) girer. Program ierisinde sadce bir kez altrlmaldr. Fonksiyon bir kere arld zaman, fonksiyondan geri dnlmez. Kayt edilen fonksiyonlar altrmak iin bekleyecektir. Aadaki rnek 2-2 GLUT tarafndan yaratlan bir pencerede renkli bir ken gstermektedir. Programn verimliliini arttrmak iin, sadece bir kez arlmas gereken fonksiyonlar, init() fonksiyonu ierisinde bulunmaktadr. Dier render ilemleri ise display() fonksiyonu ierisine konulmutur (keni izen fonksiyon) ve bu fonksiyonun ismi parametre olarak glutDispalyFunc() fonksiyonuna aktarlacaktr. rnek 2-2 GLUT kullanlarak yaplan basit bir OpenGL program
#include <GL/glut.h> void display(void) { /* tum pikselleri temizle */ glClear(GL_COLOR_BUFFER_BIT); /* koordinatlari (0.25, 0.25), * */ glBegin(GL_POLYGON); (0.75, 0.25), (0.50, 0.75) olan ucken ciz

glColor3f(1.0, 0.0, 0.0); glVertex2f(0.25, 0.25); glColor3f(0.0, 1.0, 0.0); glVertex2f(0.75, 0.25); glColor3f(0.0, 0.0, 1.0); glVertex2f(0.50, 0.75); glEnd(); glFlush(); return; } // end of void display(void) void init(void) { /* arka plan rengini belirle */ glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); /* bakis degerlerini ilkle */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return; } // end of void init(void) int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutMainLoop();

return 0; } // end int main(int, char**)

Programn ekrandaki kts aadaki gibi olacaktr.

Resim 2-2

2.8 Dardan Input Giriini Tutmak


Belli bir olay olduunda, bu olaylar tutabilmek iin GLUT, bize aadaki fonksiyonlar salamtr. glutReshapeFunc(void (*func)(int w, int h)) fonksiyonu pencerenin bykl deiecei zaman alr. glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)) ve glutMouseFunc(void (*func)(int button, int state, int x, int y)) fonksiyonlar, sizin mouse veya klavye ile ilgili ilemlerinizi tutar. Klavyenin veya farenin herhangi bir tuuna bastnzda veya bask tuttuunuzda bu olaylar meydana gelir. glutMotionFunc(void (*func)(int x, int y)) fonksiyonu, fare haraket ettmesi veya farenin dmelerine baslmas gibi olaylar tutar.

10

glutIdleFunc(void (*func)(void)) , eyer arka planda bir olay olmuyorsa yani dardan bir bilgi girii yok ise, kendisine parametre olarak aktarlan fonksiyon ismini altrr.Eyer glutIdleFunc() fonksiyonun inaktif yapmak istiyorsanz fonksiyona NULL deerini aktarn.

2.9 OpenGL lkel Geometrik Nesneleri ( OpenGL Primitives )


lkel geometrik nesnelerden anlatmak istdiimiz ey, OpenGLin izebildii basit olan ilkel noktalar, izgiler, poligonlar ve kenler gibi nesnelerdir. Bu nesnelerin birer koordinat bilgileri vardr. Bu koordinat bilgilerine vertex demekte fayda gryorum. OpenGL bu nesnelerin vertex bilgileri sayesinde bu ilkel olan geometrik ekilleri izebilmektedir. Fakat izilecek olan nesnenin nokta, izgi veya poligon olup olmadn OpenGLe bildirmek gerekir. Bu bildirim glBegin(Glenum mode) fonksiyonu tarafndan gerekletirilir. ncelikle nesnenin koordinat bilgileri OpenGL e aktarlamadan nece glBegin() fonksiyonu arlp izim modu belirlenir. Ardndan vertex bilgileri aktarlp nesnenin izimini ve izme modunun bittiini gstermek iin glEnd() fonksiyonu kullanlr. Aadaki glBegin() ve glEnd()in kullanmn gstermektedir.
glBegin(GL_POLYGON); glVertex2f(0.25, 0.25); glVertex2f(0.75, 0.25); glVertex2f(0.50, 0.75); glEnd();

11

GL_POLYGON Resim 2-3

GL_POINTS

nceki sayfada grdnz gibi, OpenGLin izecei mode glBegin tarafndan poligon olarak belirtilmitir. Bunun iin glBegin() fonksiyonuna parametre olarak aktarlan parametre GL_POLYGON dur. sayfada grdnz resim 2-3 n sol tarafnda poligon modu geerli olarak bir ken izilmitir. Eer glBegin()e aktarlacak olan mod GL_POINTS olsayd, ayn resmin sanda bulunan tane nokta gzkecekti. Resim 2-4, izim modlarn gstermektedir.

12

V1 V0 V4 V1 V2 V3 V6 V7 V0 V4 V2 V5 V3

GL_POINTS
V0 V2 V3 V4 V1 V5 V4 V0

GL_LINE

V1 V2 V3

GL_LINE_STRIP
V3

GL_LINE_LOOP

V7 V0 V4 V1 V2 V1 V5 V2 V3 V5 V4 V0 V6

GL_TRIANGLES
V2 V1 V3 V1 V0 V4

GL_TRIANGLE_STRIP
V0 V4 V3 V2 V7 V6 V5

GL_TRIANGLE_FAN

GL_QUADS
V0 V1

V1 V0 V2 V3 V4

V2 V7 V6 V5 V4 V3

GL_QUAD_STRIP

GL_POLYGON

Resim 2-4 rnekte, grdnz gibi, glEnd() fonksiyonunun parametresi yoktur. OpenGLe belirttiimiz modda, izdiimiz ilkel geometrik nesnenin izimini birtirmesi gerektiini haber vermekten baka, bir zel ilevi yoktur.

13

unu belirtmek gerekirse, glBegin() / glEnd() blou ierisinde, baka bir glBegin() / glEnd() blou bulunamaz. Ayrca, tm OpenGL fonksiyonlar, bu bloun ierisinde kullanlamayabilirler. Gerekte, sadece glVertex(), glColor(), glIndex(), glNormal(), glTextCoord(), glEvalCoord(), glEvalPoint(), glMaterial(), glEdgeFlag(), glCallList() ve glCallLists() fonksiyonlarnn eitli varyasyonlar glBegin() / glEnd() blou ierisinde kullanlabilirler.

2.10 Vertexleri Belirleme


OpenGL ile her geometrik nesne dzgn bir sraya sahip olan koordinat bilgileri ile ifade edilebilirler. Nesnenin bir koordinat bilgisini yani vertexini belirlemek iin glVertex*() komutunu kullanmamz gerekir.
void glVertex[2, 3, 4][s, i, f, d][v]( Type coords );

Bu fonksiyon, nesnenin zel bir koordinat bilgisine gre en fazla drt parametre ( parametre bilgisi olarak (x, y, z ,w) olabilir ) ve en az iki parametre parametre (parametre bilgisi olarak (x, y)) alabilir.Eyer z veya w gibi parametreleri kullanmadnz bir glVertex*() fonksiyonu kullanyorsanz, znin deeri 0 ve wnun deeri 1 olarak varsaylacaktr. glVertex*() fonksiyon ars sadece glBegin() / glEnd() blou ierisinde verimlidir. Aadaki rnek glVertex*() kullanmn basite gstermektedir.
glVertex2s(2, 3); glVertex3d(0.0, 0.0, 3.1415926535898); glVertex4f(2.3, 1.0, -2.2, 2.0); Gldouble dVect[] = {5.0, 9.0, 1992.0}; glVertex3dv(dVect);

14

lk satrdaki komut, boyutlu koordinat sistemine gre koordinat bilgisi (2, 3, 0) olan bir vertexi gstermektedir.Bildiiniz gibi bu komut, sadece iki parametre almaktadr. Yani koordinat biligileri olarak x = 2, y = 3 tr. Kullanmadmz znin deeri 0 ve wnun deeri 1 dir. kinci komut koordinat bilgileri (0.0, 0.0, 3.1415926535898) deerlerine sahip olan bir vertexi gsterir. nc satrdaki komut ise parametre olarak (2.3, 1.0, -2.2, 2.0) alr. Dikkat ederseniz wnun deeri 2.0 dr ve bu yzden demin belirttiim parametre bilgilerini yeniden incelersek w deeri x, y ve z deerlerini blecektir. Yani parametre aktarm (x/w, y/w, z/w) olarak aktarlr. Sonu olarak OpenGLin grd koordinat bilgiler (2.3, 1.0, -2.2) deilde (1.15, 0.5, -1.1) olacaktr. Son satrda ise, fonksiyona bir dizi parametre olarak atanmtr. Baz donanmlarda glVertex*() fonksiyonunun vektr formlarn kullanmak daha etklidir nk sadece tek bir parametre, grafik alt sistemine geirilmeye ihtiya duyar. zel bir donanm, tek bir seri halinde, tm koordinat bilgilerini gnderme yeteneine sahip olabilir. Buda size iyi bir performans salar.

2.11 Nokta Bykln Deitirme


Nokta bykln deitirmek iin aadaki fonksiyonu kullanmak gerkir.
void glPointSize( GLfloat size );

Varsayl olan nokta byklnn deeri yani size 1.0a eittir. Farkl nokta byklkleri iin ekrana izilecek olan piksel topluluklar antialiasing durumunun aktif veya pasif olamasna baldr.(Antialiasing izilecek olan nokta veya izgileri prssz bir ekilde izmek iin kullanlacak olan bir tekniktir.) Eyer antialiasing aktif deil ise ve verilen byklk deerleri virgll bir say ise bu say, tam sayya dntrlr ve ekranda izilecek olan noktalar kare eklinde izilirler. Mesela bykl 1.0 olan bir nokta, 1e 1 geniliinde bir piksel olarak izilir.Eer bykl 2.0 olan bir nokta enine vo boyuna 2 piksel olarak kare eklinde izilecektir

15

Antialiasingin aktif olduu durumlarda, izilecek plan noktalarn pikselleri dairesel bir ekilde izilir buda nesnenin keskin kelerinde yumuak geiler salayacaktr yani izilecek olan nesne prssz olacaktr. Bu modda bykl tamsay olmayan bir say yuvarlanmayacaktr. Programn almas esnasnda seilmi olan nokta bykln glGet() fonksiyonuyla eldeedersiniz. Bu fonsiyona GL_PONIT_SIZE parametresini aktardnzda noktann bykl bulunur.

2.12 izgi Kalnln Deitirme


Aadaki fonksiyonu kullanarak bir izginin kalnln belirleyebilirsiniz.
void glLineWidth( Glfloat width );

width yani genilik 0.0 dan byk olmaldr ve varsayl olan deeri 1.0 dr. Noktalarn iziminde antialiasing etkili olduu gibi ayn ey izgiler iin de geerlidir. Antialiasing olmadan, izilecek olan izgilerin kalnlklar, srasyla 1, 2 ve 3 ise, piksel genilikleri, yine ayn srada, 1, 2 ve piksel geniliinde olacaktr. nemle belirtmem gerekirse, ekrannz dk znrlkte alyorsa piksel genilii 1.0 olan izgiler geni olarak gzkecektir eer znrlk yksek ise izilecek olan izgi gzkmemeye yakn olabilir.

2.13 Pencere Temizleme


Bir resmi bilgisayar ekranna izmek ile kada izmek arasnda ok fark vardr. Bilgisayarn belleinde son izdiiniz resim tutulur. Yeni bir resim izmeden nce arka plan temizlemeye ihtiya duyarsnz, tabi bunu yapmak iin ncelikle arka plan temizleyecek renge sahip olamanz gerekir. Kullandnz renk gerekletireceiniz uygulamaya baldr.

16

Bilmemiz gereken ey, bitplane olarak biline grafiksel donanmda her pikselin renginin nasl tutulduudur. Renklerin tutulmasna dair iki ynten mevcut.Birinci yntem, bir pikselin krmz, yeil, mavi ve alfa deerlerinin direk olarak bitplane ierisinde korunmas ve dier bir yntem ise renk index modudur. Aadaki komut satrlar RGBA modunda pencereyi siyaha temizlemektedir.
glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT);

lk satrdaki komut temizleme rengini siyah yapmaktadr ve ardndan gelen komut ise seilmi olan temizleme rengini dikkate alarak pencereyi temizler. glClear() komutuna aktarlm olan tek parametre hangi buffern temizleneceini OpenGLe bildirmektedir. Bu durumda resmin sakl tutulduu renk buffer program tarafndan temizlenecektir. Aada glClear() ile glClearColor() fonksiyonlarnn prototipleri ve komutlarn ilevleri aklanmaktadr. void glClear(Glbitfield mask) fonksiyonu mask olarak belirtilmi parametreye gre bufferlar temizler. void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) fonksiyonu RGBA modda temizlemek iin kullanlacak olan rengi belirler. Varsaylan temizleme deerleri (0.0, 0.0, 0.0, 0.0) olduundan dolay siyahtr.

17

2.14 Nesnenin Rengini Belirleme


OpenGL ile, izilecek olan bir nesnenin eklini ifade etmek, nesnenin rengini ifade etmekten bamszdr. Nezaman bir nesne izileceinde, o anki renk emas kullanlarak nesne izilir. Genel olarak OpenGL programcsnn yapaca ilk i rengi veya renk emasn ayarlamak ve sonra ise nesneyi izmektir. O anki renk veya renk emas deimeyinceye kadar tm nesneler bu rengi veya renk emasn kullanrak izilirler. Aadaki rnei incelerseniz, izilecek olan nesnelerin yalanc kodunu greceksiniz.
SetCurrentColor(RED); DrawObject(A); DrawObject(B); SetCurrentColor(GREEN); SetCurrentColor(BLUE); DrawObject(C);

Yukardaki rnekte A ve B nesneleri krmz olarak ve C nesnesi ise mavi olarak izilecektir. Drdnc satrdaki SetCurrenColor(GREEN) komutu gereksiz yere kullanlmtr. Bir rengi belirlemek iin, glColor3f() komutunu kullann. Bu fonksiyon 0.0 ile 1.0 arasnda tane argman almaktadr. Parametreleri srasyla red, green ve blue dur. Bu parametrelerin deerlerinin karmndan yeni renkler yaratabilirsiniz. 0.0 deeri bileeni yani rengi kullanmayacamz anlamna gelmektedir. 1.0 ise tam tersidir. Mesela glColor3f(1.0, 0.0, 0.0); fonksiyonunu kulandmzda sistemin bir nesneyi parlak krmz bir renkte izecei anlamna gelmektedir yeil ve mavi renkler kullanlmaz. Tm sfrlar rengi siyah, tm birler ise rengi beyaz yapar. Tm renk deerle-

18

rini 0.5 olarak ayarlarsak rengimiz griye kaacaktr. Bir sonraki sayfada sekiz tane renk ayarlamas gsterilmektedir.
glColor3f(0.0, 0.0, 0.0); glColor3f(1.0, 0.0, 0.0); glColor3f(0.0, 1.0, 0.0); glColor3f(1.0, 1.0, 0.0); glColor3f(0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); glColor3f(0.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0); siyah krmz yeil sar mavi magenta iyan beyaz

2.15 Koordinat evrimleri


Koordinat evrimleri boyutlu bir ortamda varlklar gerekletirme, dndrme ve haraket ettirme gibi olanaklar salar. Bu evrimler, nesneleri ve nesnelerin koordinat sitemlerini direk olarak modifiye eder.(degistirir) Mesela, modelinizin koordinat siteminde bir dndrme ilemi yaptnzda, modelinizi izeceiniz zaman, o da deitirmi olduunuz koordiant eksenine gre dnecektir. Nesneler izilmeden nce, tip transformasyondan yani dnmden geer. Viewing transformation: Kamerann yerinin belirlendii transformasyondur. Modeling transformation: Nesnenin ekranda hareketini salayan transformasyondur. Projection transformation: Kamerann bak hacmini belirleyen transformasyondur.

19

Viewing transformation, yazdnz kod ierisinde modelling transformationdan nce gelmelidir fakat izim yapmadan nce projection ve viewport transformationlar yani dnmlerini belirleyebilirsiniz. Aadaki ekil resim 2-5 bilgisayarnzda hangi ilemlerin srayla olduunu gstermektedir.

Nesne Koordinatlar (x, y, z, w)

Vertex

Modelview Matris

Gz Koordinatlar Projection Matris

Kesme Koordinatlar Perspektiv Blm Normalletirilmi Ara Koordinatlar Perspective Blm Viewport Transformation Pencere Koordinatlar

Resim 2-5

Vertex Dnmnn Safhalar

Viewing, modeling ve projection transformationlarn belirlemek iin, 4X4 lk bir M matris tanmlamas yapmanz gerekir.Bu matris, istenilen transformasyonlar gerekletirebilmek iin ekrandaki her bir v verteksinin koordinatlaryla arplr. v = Mv

20

(Not: vertexlerin drt tane koordinat olduunu nemle vurgulamam gerekir. Fakat bir ok durumda w, 1e eit ve iki boyutlu koordinat sistemi iin z deeri 0a eittir.)Viewing ve modeling transformasyonlar otomatik olarak yzey normal vektrlerine ve ek olarak vertexlere uygulanmaktadr.( Normal vektrleri sadece gz koordinatlarnda kullanlr.Bu, normal vektrnn vertex verisi ile olan ilikisini uygun bir ekilde saladn temin etmektedir. Belirttiiniz viewing ve modelling transformasyonlar, modelview matrisini oluturmak iin bir araya getirilirler. Gz koordinatlarn vermek iin, gelen nesnenin koordinat bilgilerine bu matris uygulanmaktadr.Eer nesnenin ekranda gzkmeyen ksmlarn silmek gerekiyorsa, kesme yzeyleri uygulanr. Bundan sonra, OpenGL, projection matrisini kesme koordinatlarn verebilmek iin uygulayacaktr. Bu sayede kamerann nesneyi gsteremedii ksmlar kesilecektir, yani gzkmeyecektir. Bu noktadan sonra perspektif blm, normallemi ara koordinatlarn retebilmek iin koordinat deerlerini w ile blerek yerine getirilir. Son olarak ise, viewport transformasyonu uygulanarak, dntrlm koordinatlar pencere koordinatlarna evrilir. Bylece viewport boyutlar zerinde, resim ile oynamak iin, eitli manipulasyonlar uygulayabilirsiniz.

2.16 Basit bir rnek: Bir Kp izme


rnek 2-3, yarattnz pencerede, wireframe olarak bir kp izmektedir.Wireframe olarak sylenilen ey kpn sadece gzken kenarlarn gstermek anlamna gelmektedir, kpn yzeyleri izilmez. Viewing transformasyonuda gluLookAt() ile kamerann nereye yerletirilecei ve nasl bir ekilde modeli izleyecei belirtilir. Ek olarak projection ve viewport transformasyonlar (bezen transformation kelimesini tranformasyon veya dnm olarak yazabilirim) belirlenecektir. Resim 2-6 ise ekranda oluacak olan kp gstermektedir. rnek 2-3 Dntrlm kp

21

#include <windows.h> #include <GL/glut.h> void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); } // end of void init(void) void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glLoadIdentity(); /* viewing transformation */ gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //glTranslatef(0.0, 0.0, -5.0); glScalef(1.0, 2.0, 1.0); glutWireCube(1.0); glFlush(); } // end of void display(void) void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); // gluPerspective(60.0, 1.0, 1.5, 20.0); glMatrixMode(GL_MODELVIEW); } // end of void reshape(int, int) int main(int argc, char** argv) {

22

glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; } // end of int main(int, char**)

Resim 2-6

2.17 Vieving Transformation


Viewing transformation kamerann yerinin belirlenmesi ve modele ynlendirilmesidir. Bu kodda, viewing transformation belirlenmeden nce, program ierisinde o anda kullanlan matris glLoadIdentity() fonksiyonu ile identity matris olarak yklenir. Identity matris, diagonel elemanlar 1e ve dier tm elemanlar 0a eit olan bir kare matristir. (Program ierisinde o anda kullanlmakta olan matrise current matris diyelim)

23

Bu aama gereklidir, nk belirtilen bir matris current matris ile arplp tekrar current matrise atanr. Dolays ile yapacamz ilemlere dikkat etmemiz gerekir. Eer current matrisini identity olarak ilklemezseniz yani temizlemezseniz, baz istenmeyen sonular elde edersiniz. rnekte, matris ilklendikten sonra, gluLookAt() fonksiyonu ile viewing transformasyonu belirlenmektedir. Fonksiyona aktarlan argmanlar, kamerann( gz koordinatlar) nereye yerletirileceini, nereye ynlendirileceini ve nasl bir ekilde modeli gstereceini belirtirler. Kodda kullanlan argmanlar kamerann (0, 0, 5) noktasnda olduunu, kamerann lensinin (0, 0, 0) noktasna ynlendirildiini ve up-vectr olarak (0, 1, 0) ekim yaptn anlatmaktadr. gluLookAt() fonksiyonunu kullanmam olsaydk, kamerann varsayl olan deerleri kullanlm olurdu. Varsayl olarak, kamera koordinat sistemini merkezinde, lensi negatif z eksenine evrilmi ve up vektr olarak (0, 1, 0) noktasna gre ayarlanm olurdu. rnekte ise kameray 5 birim, pozitif z ekseni dorultusunda kaydrlmtr.
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz);

(eyex, eyey, eyez) koordinatlar kamerann yerini ayarlar. (centerx, centery, centerz) koordinatlar kamerann hangi noktaya bakacan tanmlamaktadr. Son olan koordinat parametreleri ise (upx, upy, upz) kamerann up-vektrn belirtmektedir. Resim 2-7 bu parametrelerin, kamera zerindeki kullanmn gstermektedir.

24

( upx, upy, upz )

Kamera

( centerx, centery, centerz )

( eyex, eyey, eyez )

Resim 2-7

2.18 glRotate*() ve glTranslate*() Fonksiyonlarnn Kullanm


gluLookAt() fonksiyonunu kullanmadan, baka yntemler ile bu fonksiyonu gerekletirebiliriz. Bu yntem ise modelview transformasyon fonksiyonlarndan olan glRotate*() ve glTraslate*() fonksiyonlardr. Bu fonksiyonlar duraan bir kameraya, boyutlu ortamdaki fonksiyonellii salarlar. Kameray hareket ettirmek yerine kamerann gsterdii modelleri hareket ettirmek de dier bir yntemdir. rnek 2-3teki koda tekrar bakacak olursanz, display() fonksiyonu ierisinde n ift ters bl iareti ile pasif hale getirilmi glTranslatef(0.0, 0.0, -5.0) fonksiyonun greceksiniz. Bu fonksiyonun nndeki ters bl iaretlerini kaldrp, gluLookAt() fonksiyonun pasif hale getirirseniz ayn etkiyi greceksiniz. Bildiiniz gibi gluLookAt() fonksiyonunu kullanmadnzda kamera, koordinat sisteminin merkezine varsayl olarak yerletirilir. Koordinat sistemini, kameradan 5 birim uzaa yani negatif z ekseni dorultusunda kaydrrsanz kpn grnmnde bir deiiklik olmayacaktr. Aadaki display() fonksiyonu bu zeti gstermektedir.
void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glLoadIdentity(); /* viewing transformation */

25

//gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glTranslatef(0.0, 0.0, -5.0); glScalef(1.0, 2.0, 1.0); glutWireCube(1.0); glFlush(); } // end of void display(void)

2.19 Modeling Transformation


Modeling transformasyonlar, nesneleri hareket ettirerek, dndrerek, boyutunda deiiklik yaparak, bu modellerin orientasyonunda ve pozisyonunda eitli deiiklikler yapmamza izin verir. Bu ilemlerin birini veya bir ounu birlikte kullanarak gerekletirebilirsiniz. Translation: Belirtilen bir eksen zerinde nesnenin hareketini salar. Rotating: Bir eksen etrafnda, modelin kendi evresinde dndrme ilemidir. Scalig: Nesnenin boyutunu byltmek veya kltmek gibi fonksiyonelliklere sahip olan bir gerekletirimdir. Bu zellik sayesinde nesneye en veya boy gibi eitli boyut deiiklii kazandrabilirsiniz

Ekrannzda izeceiniz nesne iin belirlemi olduunuz modeling transformasyon fonksiyonlarnn sras nemlidir. rnek vermek gerekirse, Resim 2-8, translation ileminden sonra rotation ilemini ve rotation ileminden sonra translation ilemini gstermektedir. ki farkl ilemin etkileri birbirlerinden farkldr. Farz edelim ki, koordinat sisteminin merkezine yerlemi olan bir ok olsun. Uygulayacamz ilk transformasyon

26

ilemi bu oku z eksenine gre 30 derece dndrmektir yani rotation ilemidir. Ardndan x ekseni dorultusunda koordinat sistemini 5 birim tama yapalm. Eer bu ilemi tersini yaparsak elde edeceimiz sonu ilkinden farkl olacaktr.

+y -x +x -x

+y +x -x

+y +x

-y

-y

-y

+y -x +x -x

+y

+y +x -x

+y

+x

-y

-y

-y

-y

Resim 2-8

2.20 Modelview Matrisi


Modelview matrisi, nesneleri koordinat sisteminin istenilen bir yerine yerletirmek ve onlar ynetmek iin koordinat sistemini tanmlar. 4e 4lk bir matristir verteksler ve transformasyonlar ile arplrlar. Bu arpm ileminin sonunda, vertekslere uygulana transformasyonlarn sonularn yanstacak yeni bir matris retilir. OpenGL komutu olan glMatrixMode() fonksiyonu aracl ile modelview matrisini deitirmek isteyebilirsiniz. Bu fonksiyonun prototipi aadaki satrda belirtilmitir

27

void glMatrixMode( GLenum mode );

Herhangi bir transformation ilemini armadan nce, hangi matris modu zerinde Modifikasyonlar uygulayacanz belirtmeniz gerekir. Modelview modunda ilem yapmak istiyorsanz parametre olarak GL_MODELVIEW parametresini aktarn. glMatrixMode() iin aktarlacak dier parametreler ise GL_PROJECTION ve GL_TEXTURE argmanlardr. Projection matrisini belirtmek iin GL_PROJECTION kullanlr ve texture matrisi iin ise GL_TEXTURE bunu belirtmektedir. Bir ok durumda, bu matrisi current matris olarak ayarladktan sonra modelview matrisini identity matris olarak ilkleyin. Bunu yapabilmek iin glLoadIdentity() fonksiyonu kullann.

2.21 Translation
boyutlu bir dnyada, nesneyi bir yerden baka bir yere tamak iin bu ilem kullanlmaktadr. Bunu yapabilmek iin glTanslatef() ve glTranslated() fonksiyonlar bu ilemi gerekletirir.
void glTranslatef(GLfloat x, GLfloat y, GLfloat z); void glTranslated(GLdouble x, GLdouble y, GLdouble z);

Bu iki fonksiyon arasndaki tek fark aldklar parametre tiplerinin birbirlerinden farkl olmaldr. glTranslatef(), float tipinde ve glTranslated() fonksiyonu double tipinde parametre alr. Farzedin ki, bir kb koordinat sisteminin merkezinden (5, 5, 5) noktasna tamak istiyorsunuz. lk olarak modelview matrisini ykleyin ve sonra ilkleyin. Aadaki kod yapacamz ilemi gerekletirir ve resim 2-9 bunun sonucunu gsterir.

28

glMatrixMode(GL_PROJECTION); glLoadIdentity(); glTranslatef(5.0, 5.0, 5.0); // kb iz DrawCube();

+y -z

(5, 5, 5)

-x

+x

+z

-y

Resim 2-9

2.22 Rotating
OpenGLde rotating, glRotate*() fonksiyonu ile gerekletirilmektedir.
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);

Tekrar sylemek gerekirse, glTranslate*() fonksiyonunda olduu gibi bu iki fonksiyon arasndaki tek fark aldklar parametre tiplerinin birbirlerinden farkl olmalardr. x, y ve z parametrelerine gre, nesneyi belirli bir a lsnde bu koordinat eksenleri etrafnda dndrebilirsiniz. Mesela izmi olduunuz bir modeli y ekseni etrafnda yelkovan ynne, 135 derece dndrmek istiyoruz. Bunun iin aadaki bu ilemi bizim iin yapmaktadr.

29

glRotatef(135.0, 0.0, 1.0, 0.0);

y argmann ald 1.0 deeri, y ekseni yndeki birim vektr belirtmektedir. stediiniz eksene gre, rotate ilemini yapabilmeniz iin sadece birim vektrn belirtmeniz gerekir. Resim 2-10 glRotate*() fonksiyonunun nasl altn gstermektedir.

+y -z

-x

+x

+z -y

Resim 2-10 Eer ekli saat ynnn tersine evirmek istiyorsanz, ay negatif olarak ayarlamanz gerekir. Bahsettiimiz ayn rotating rnei iin nesneyi saat ynnn tersinde 135 derece y ekseni evresinde dndrmek istiyorsak aadaki komutu yazmamz gerekmektedir.
glRotatef(-135.0, 0.0, 1.0, 0.0);

x, y, z parametrelerini kullanarak modeli istediimiz yne evirebiliriz. Unutmayn ki koordinat ekseni bu dnten etkilenecektir.

30

2.23 Scaling
Modelin boyutundaki ayarlamalar yapmak iin scaling ilemi kullanlmaktadr. Nesnenin boyutlar eksenlere gre uzatlabilip ksaltlabilir. Bunu OpenGLin salad glScale*() fonksiyonu ile yapabiliriz.
void glScalef(GLfloat x, GLfloat y, GLfloat z); void glScaled(GLdouble x, GLdouble y, GLdouble z);

x, y, z parametrelerine geirilen deerler her bir eksenin scale faktrn belirler. rnek olarak aadaki satr nesnenin her boyutunu 2 katna kartmaktadr.
glScalef(2.0, 2.0, 2.0);

Mesela, izdiimiz bir kbn derinlik ve yksekliini deitirmeden x ekseni zerindeki genilini 2 katna kartmak istiyoruz.
glScalef(2.0, 1.0, 1.0);

Eer nesneyi kltmek istiyorsanz, kullanacanz deerler 1den kk olmaldr.


+y -z +y -z

-x

+x

-x

+x

+z

+z

-y

-y

glScalef(2.0, 2.0, 2.0);

glScalef(0.5, 0.5, 0.5);

31

Aada kbn hacmini 8 katna kartan rnek gsterilmektedir.


glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(2.0, 2.0, 2.0); DrawCube(); // kb iz

2.24 Matris Ytlar


Yarattnz modelview ve projection matrisleri, ykleme ve arpma ilemeleri sadece buz dann grnen yzn gstermektedirler. Bu matrislerin her biri matrislerin ytnn en st elemanlardr. Matris yt bizim iin ideal bir mekanizma salamaktadr. Gemiteki transformasyonlar hatrlayabilmek iin bu yap kullanlmaktadr. tip matris yt vardr. Modelview Matris Yt Projection Matris Yt Texture Matris Yt

Matrislerin ytlar hiyerarik olarak nesneleri meydana getirmek iin kullanldrkar. Bu karmak modeller basit olan modellerden yaratlrlar. rnein, kutulardan nasl bir robot oluturulduunu dnn. Eer robotu bileenlerine ayrrsanz, robotun bir gvdesinin, kollarnn, bann ve bunun gibi bileenlerinin olduunu grrsnz. Bu ana kadar yaptmz matris ilemleri hep current matris ile ilgiliydi. Aslnda bu matris ytn en st elemandr.Yt ilemlerini yerine getiren komutlar ile, ytn stnde bulunan matrisi kontrol edebiliriz. Bildiiniz gibi yt ilemelerinde en sklkla kullanlan iki komut vardr. Bu komutlar push() ve pop() komutlardr. Yta bilgi gndermek iin ytn en stne bu bilgi kopyalanr. Bu ilem push() ilemidir. Yttn en stnden bilginin atlabilmesi iin pop() ilemi kullanlmaktadr. OpenGL bu gibi komutlar bize salamtr. glPushMatrix() ve glPopMatrix() glPushMatrix()

32

current matrisi kopyalar ve ytn en stne bu kopyalanm bilgiyi yerletirir. glPopMatrix() ise ytn en stndeki bilgiyi ekip kartr. Hatrlayn: ytn en st current matristir. Resim 2-11 yt matrisini gsterir.

glPushMatrix()

glPopMatrix()

Matris Yt Resim 2-11 glPushMatrix() ve glPopMatrix() iin yapacamz en uygun rnek, bir robot kolu olacaktr. Bu rnek sayesinde bu iki fonksiyonun ne ie yaradn bu rnek sayesinde anlayacaksnz. Bu blmde robot kolunun ikiden fazla segmenti vardr. Aadaki resim 2-12 izilecek olan robot kolunu gstermektedir.

33

Resim 2-12 Kolun segmentlerini izebilmek iin ncelikle boyutlarn deitirebileceiniz bir kbe ihtiyacnz olmal, fakat ilk olarak her segmentin kendi koordinat eksenlerine yerletirmek iin uygun modelleme transformasyonlarn armak gerekir. lk olarak yerel koordinat sisteminin merkezi izilen kbn merkezinde olacandan dolay, kbn bir kenarna yerel koordinat sistemini tamaya ihtiyacnz olacak. Dier bir koulda, kp pivot noktasna gre deil de merkezine gre dnecektir. Pivot noktasn yaratmak iin glTranslate*() fonksiyonunu ve bu pivot noktasna gre glRotate*() fonksiyonunu ardktan sonra, kbn merkezine doru evrimi yapn. Daha sonra kp izilmeden nce, kbn boyutlarn deitirin. glScale*() fonksiyonu dier segmentleri etkileyebilir ve bunu engellemek iin glPushMatrix ve glPopMatrix fonksiyonlarn kullanmak faydal olacaktr. Aada robot kolunun ilk segmenti iin, program kodunun nasl bir eye benzediini grn.
glTranslatef(-1.0, 0.0, 0.0); glRotatef((GLfloat) shoulder, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0);

34

glPushMatrix(); glScalef(2.0, 0.4, 1.0); glutWireCube(1.0); glPopMatrix();

kinci segmenti yaratabilmek iin, lokal koordinat sistemini bir sonraki pivot noktaSna hareket ettirmemiz gerekiyor. Koordinat sistemi nceden dndne gre, x ekseni, dnm olan kolun uzunluu dorultusunda oktan yerlemi olacaktr. Bu sebepten dolaydr ki, x ekseni dorultusunda transformasyon yapmak lokal koordinat sistemini bir sonraki pivot noktasna hareket ettirecektir. Bu noktaya koordinat sistemin tandktan sonra, ilk olarak kullanm olduunuz kod blounu yeniden kullanarak, ikinci segmenti izebilirsiniz. Bu ilem sonsuz sayda segmentler iin geerlidir. rnek 2-4 deki program kodunun tm gsterilmektedir.

rnek 2-4
#include <stdlib.h> #include <GL/glut.h> static GLfloat shoulder = 0.0, elbow = 0.0, wrist1 = 0.0, finger1 = 0.0, b_wrist = 0.0, b_finger = 0.0; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); return; } // end of void init(void) void reshape(int w, int h) {

35

glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-2.0, 0.0, -5.0); return; } // end of reshape(int, int) void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glPushMatrix(); glTranslatef(-1.0, 0.0, 0.0); glRotatef((GLfloat) shoulder, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); glPushMatrix(); glScalef(2.0, 0.4, 1.0); glutWireCube(1.0); glPopMatrix(); glTranslatef(1.0, 0.0, 0.0); glRotatef((GLfloat) elbow, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); glPushMatrix(); glScalef(2.0, 0.4, 1.0); glutWireCube(1.0); glPopMatrix();

glPushMatrix();

36

glTranslatef(1.0, 0.125, 0.25); glRotatef((GLfloat)wrist1, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1 , 0.25); glutWireCube(1.0); glPopMatrix(); glTranslatef(0.25, 0.0, 0.0); glRotatef((GLfloat) finger1, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1 , 0.25); glutWireCube(1.0); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslatef(1.0, 0.125, -0.25); glRotatef((GLfloat)wrist1, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1, 0.25); glutWireCube(1.0); glPopMatrix(); glTranslatef(0.25, 0.0, 0.0); glRotatef((GLfloat) finger1, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1, 0.25); glutWireCube(1.0); glPopMatrix(); glPopMatrix();

37

glPushMatrix(); glTranslatef(1.0, -0.125, 0.0); glRotatef((GLfloat)b_wrist, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1, 0.25); glutWireCube(1.0); glPopMatrix(); glTranslatef(0.25, 0.0, 0.0); glRotatef((GLfloat) b_finger, 0.0, 0.0, 1.0); glTranslatef(0.25, 0.0, 0.0); glPushMatrix(); glScalef(0.5, 0.1, 0.25); glutWireCube(1.0); glPopMatrix(); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); return; } // end of void display(void) void keyboard(unsigned char key, int x, int y) { switch (key) { case 's': shoulder += 5; if (shoulder > 360.0) shoulder -= 360.0; glutPostRedisplay(); break; case 'S': shoulder -= 5;

38

if (shoulder < 360.0) shoulder += 360.0; glutPostRedisplay(); break; case 'e': elbow += 5; if (elbow > 360.0) elbow -= 360.0; glutPostRedisplay(); break; case 'E': elbow -= 5; if (elbow < 360.0) elbow += 360.0; glutPostRedisplay(); break; case 'd': wrist1 += 5; if (wrist1 > 360.0) wrist1 -= 360.0; glutPostRedisplay(); break; case 'D': wrist1 -= 5; if (wrist1 < 360.0) wrist1 += 360.0; glutPostRedisplay(); break; case 'f': finger1 += 5; if (finger1 > 360.0) finger1 -= 360.0; glutPostRedisplay(); break; case 'F': finger1 -= 5; if (finger1 < 360.0) finger1 += 360.0; glutPostRedisplay(); break; case 'v': b_finger += 5; if (b_finger > 360.0) b_finger -= 360.0; glutPostRedisplay();

39

break; case 'V': b_finger -= 5; if (b_finger < 360.0) b_finger += 360.0; glutPostRedisplay(); break; case 'c': b_wrist += 5; if (b_wrist > 360.0) b_wrist -= 360.0; glutPostRedisplay(); break; case 'C': b_wrist -= 5; if (b_wrist < 360.0) b_wrist += 360.0; glutPostRedisplay(); break; case 27: exit(0); break; default: break; } // end of switch (key) } // end of void keyboard(unsigned char, int , int) int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(640, 480); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0;

40

} // end of int main(int, int)

2.25 OpenGL de Iklandrma


Konu olarak, boyutlu grafik kavramlar asndan nesneler iin klandrma byk nem tamaktadr. Iklandrma bilgisayar ortamnda, yarattnz nesnelere bir gereklik katmaktadr. u ana kadar ilemi olduumuz konularda nesnelerin nasl yaratldn, bu nesneleri nasl hareket ettirdiimizi ve boyutlarndaki deiimi nasl gerekletirdiimizi anlatmaya altk. imdi ise bu nesneleri klandrma fonksiyonlar kullanarak canlandrmaya balayacaz. Gerek dnyada nesneler nasl yanstarak, kendi renklerini bize gsteriyorsa, krmz, yeil ve mavi bileenlerine yaklatrarak, OpenGL k ve klandrmay hesaplamaktadr. Burada sylenmek istenene ey, n yayd krmz, yeil ve mavi k miktarlarna bal olarak, bir n yayd renk belirlenir. Ik bir yzeye arptnda, yzey tarafndan yanstlacak olan krmz, yeil ve mavi k tonlarnn yzdelerini belirtmek iin, OpenGL yzeyin materyalini kullanmaktadr. OpenGL, drt k bileenini kullanarak, gerek dnyadaki klandrmay gerekletirmektedir. Ambient Iklandrma, belirli bir ynden gelen k kaynana benzememektedir. Bunun anlam, n hangi kaynaktan geldiini belirlemenin imkansz olduu anlamna gelir yani n her ynden geldiini ortaya koymaktadr. Diffuse Iklandrma, belirli bir ynden gelmektedir, fakat k yzeye arptnda tm ynlere eit olarak yanstlmaktadr. Gznzn hangi pozisyonda olduuna baklmadan, n arpt yzey, gze eit olarak parlak grnr.

41

Specular Iklandrma, belirli bit ynden gelerek yzeye arpar ve nceden belirlenmi bir yne doru yansmaktadr yani eit olarak yansma yoktur. Emissive Iklandrma, nesneden kan k anlamna gelmektedir. OpenGL klandrma ynteminde, nesnenin yzeyinden yansyan renk, nesneye daha ok younluk katar, fakat bu dier k kaynaklarn etkilemez.

2.26 Materyal Renkler


OpenGL klandrma modeli, kendisinin yanstmakta olduu krmz, yeil ve mavi Iklarn yzdeleri materyalin rengini etkilemektedir. rnek olarak, krmz bir top, tm gelen krmz yanstr ve dier gelmekte olan yeil ve mavi absorbe eder. Eer bu topu beyaz k altnda gzlyorsanz, topun tm krmz rengi yanstlacak ve top krmz olarak grlecektir. Eer top krmz n az olduu bir yerde bulunuyorsa, top yine krmz olarak, fakat az yeil n bulunduu yerde top bulunuyorsa, ayn top siyah olarak gzkr. nk yeil k absorbe edilmektedir ve orada krmz k kayna yoktur, bu yzden k yanstlamaz. Iklarda olduu gibi, materyallerinde farkl ambient, diffuse ve specular renklere sahiptirler. Bu renkler, materyalin ambient, diffuse ve specular yansmalarn belirler. Bir materyali ambient yansmas, her gelen k kaynann ambient bileeni ile, diffuse yansmas n diffuse bileeni ile ve specular yansmas specular bileeni ile btnletrilmektedir. Ambient ve diffuse yansmalar materyalin rengini belirler. Specular yansma genellikle beyaz yada gridir bu yzden yzey zerindeki specular olan kl ve detayl olan ksm, orada k kaynann specular younluunu olmasn sonlandrr. Eer parlak bir krmz plastik topun beyaz k altnda olduunu dnrseniz, bu topun byk bir yzeyinin krmz, fakat parlakln fazla olduu blgenin beyaz olduunu greceksiniz.

42

Iklar iin belirlenmi olan renk bileenleri, materyaller iin, daha farkl bir anlama gelmektedir. Bir ele alrsak, her renk iin, saylar tam younluk yzdesine uygun dmektedir. In krmz, yeil ve mavi bileenlerinin deerinin hepsi 1.0 a eit ise, k parlak bir beyaz k kayna olmaktadr. Eer tm deerler 0.5 e eit olduunda, k kayna yine beyaz olur fakat younlu %50 orannda azalcaktr. Ik bileenlerinden krmz ve yeilin deeri !.0 a, mavinin deeri ise 0.0 a eit ise, k yeil olarak grnr. Materyaller iin, saylar yansmakta n bileenler deeri ile arplmaktadr. Mesela materyalin kmz deeri 1.0 a, yeil deeri 0.5 e ve mavi deeri 0.0 a eit oluyorsa, materyal gelen klardan krmz n %100 n, yeil n %50sini ve mavi n %0 n yanstmakta olduunu belirtmektedir. Dier bir anlatm ekli ile anlatmaya alrsak, elimizde bir k kaynaklarnn deerleri olsun. Bu deerler ( IK, IY, IM ) ve materyalin deerleri ise ( MK, MY, MM ) olsun. Dier yansma etkilerini gze almasak, gzn grecei deerler yani cismin yanstaca k deerleri ( IK * MK, IY * MY, IM * MM ) olmaktadr. Benzer olarak, iki k kayna kullanyorsanz, yani gze gnderilecek deerler ( K1, Y1, M1 ) ve ( K2, Y2, M2 ), OpenGL bu bileenleri toplayacaktr ( K1 + K2, Y1 + Y2, M1 + M2 ). Bu toplama ilemlerinden herhangi biri 1 den byk karsa toplama ilemi 1 olarak alnr.

2.27 Kk Bir rnek: Krmz aydanlk


Uygulamanza, klandrmay eklemek iin aadaki aamalar yapmakta fayda var. 1. Her nesnenin her verteksi iin normal vektrleri tanmlayn. Bu normaller k kaynayla alakal olarak nesnenin yerini belirlerler. 2. Bir veya birden fazla yaratn, sein ve belirli konumlara getirin.

43

3. Bir klandrma modelin yaratn. 4. Nesnenin materyal zelliklerini tanmlayn. Aadaki rnek 2-5 bu ilemleri gerekletirmektedir. Bu rnekte tek bir k kayna altnda izilmi olan krmz bir aydanlk izilmektedir. rnek 2-5 Krmz aydanlk
#include <GL/glut.h> #include <GL/glu.h> GLfloat rotate_y = 0.0;

void draw_net(GLfloat size, GLint LinesX, GLint LinesZ) { int xc, zc; glBegin(GL_LINES); for (xc = 0; xc < LinesX; xc++) { glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / 2.0); glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / -2.0); } // end of for (xc = 0; xc < LinesX; xc++) for (zc = 0; zc < LinesZ; zc++) {

44

glVertex3f( size / 2.0, 0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); glVertex3f( size / -2.0, 0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); } // end of for (zc = 0; zc < LinesZ; zc++) glEnd(); return; } // end of void draw_net(GLfloat, GLint, GLint) void init(void) { GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat material_ambient[] = {0.23, 0.0, 0.0, 1.0}; GLfloat material_diffuse[] = {0.44, 0.0, 0.0, 1.0}; GLfloat material_specular[] = {0.33, 0.33, 0.52, 1.0}; GLfloat material_emission[] = {0.0, 0.0, 0.0, 0.0}; GLfloat material_shininess = 10; glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glMaterialfv(GL_FRONT, GL_AMBIENT, material_ambient);

45

glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular); glMaterialfv(GL_FRONT, GL_EMISSION, material_emission); glMaterialfv(GL_FRONT, GL_SHININESS, &material_shininess); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return; } // end of init(void) void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rotate_y, 0.0, 1.0, 0.0); glPushMatrix(); glTranslatef(0.0, 0.55, 0.0); glutSolidTeapot(0.75); glPopMatrix(); glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 1.0); draw_net(5, 11, 11); glEnable(GL_LIGHTING); glPopMatrix(); glutSwapBuffers(); return; } // end of void display(void)

46

void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 2.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); return; } // end of void reshape(GLfloat, GLfloat) void rotate_teapot(void) { rotate_y += 0.5; if (rotate_y > 360.0) rotate_y -= 360.0; glutPostRedisplay(); return; } // end of rotate_teapot(void) int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("Teapot"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutIdleFunc(rotate_teapot); glutMainLoop();

47

return 0; } // end of int main(int, char**)

rnei incelemeye balayalm. Ik kaynaklarnn bir ok zellikleri vardr, bunlar renk, pozisyon ve n yndr. Bu tm zellikleri belirlemek iin kullanlan komut glLight*() fonksiyonudur. Fonksiyon argman almaktadr. Fonksiyonun prototipi aada belirtilmitir.
void glLight[if]v( GLenum light, GLenum pname, Type *param );

lk parametre olan light parametresi zellii belirlenecek olan k kaynan belirtir. Bu kaynaklar GL_LIGHT0, GL_LIGHT1, GL_LIGH7 olan sekiz tane k kayna mevcuttur. In karakteristiini belirleyen parametre pname parametresidir ve tablo 2-2 bu parametrenin alaca deerleri listelemektedir. pname parametresine gre param parametresinin alaca deerler vardr. Bu parametre bir vektr gsteren bir iaretidir. Tablo 2-2 glLight*() Parametreleri

48

Parametre
GL_AMBIENT GL_DIFFUSE

Varsayl Deerler
(0.0, 0.0, 0.0, 0.0) (1.0, 1.0, 1.0, 1.0) (0.0, 0.0, 0.0, 0.0)

Anlam
Ambient younluu Diffuse younluu (light 0 iin) (Dier klar iin) specular younluu (light 0 iin) (Dier klar iin) (x, y, z, w) pozisyon

GL_SPECULAR

(1.0, 1.0, 1.0, 1.0) (0.0, 0.0, 0.0, 0.0)

GL_POSITION

(0.0, 0.0, 1.0, 0.0)

Gsterilecek daha bir ok parametre var fakat u anda bizim ilgileneceimiz parametreler uygulamalarmz iin yeterli. rnei dikkatlice incelerseniz init() fonksiyonu iinde n ambient, diffuse, specular ve pozisyon bilgileri tanmlanmtr.
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

Greceiniz gibi, parametre deerleri iin diziler tanmlanm ve glLightfv() fonksiyonu n zelliklerini belirlemek iin tekrar tekrar arlmtr. Bu zellikler ayarlandktan sonra, klandrma olayn ve k kaynan aktifletirmeye geldi. Temel olarak klandrmann aktif hale gelebilmesi iin glEnable() fonksiyonunu kullanmak gerekir.

49

glEnable(GL_LIGHTING);

Bu ilemin ardndan hangi k kaynan aktif hale getirmek istediimizi OpenGL e anlatmak ii yine ayn fonksiyonu yani glEnable() fonksiyonunu kullanmamz gerekir. zelliklerini ayarladmz k kayna light 0 olduuna gre aadaki kod bu k kaynan aktif hale getirecektir.
glEnable(GL_LIGHT0);

I aktif ettikten sonra ksaca anlatmak istediimiz ey n bulunduu konum, yani n pozisyonu ile ilgili nemli bir konuyu dile getirmek istiyoruz. Ik pozisyonu ayarlanrken kullanlan drt farkl deerler var ( x, y, z, w ). Bu deerleri ilk yani x, y, z tahmin edeceiniz gibi k kaynann koordinatlarn belirtmektedir. Peki ya drdnc parametre ne anlama gelmektedir ? Drdnc parametreyi 0.0 a eit olduunda k kaynann sonsuz uzaklktan bir yerden geldii anlamna gelmektedir ve bu sebepten dolay k kaynandan yaylan nlar parelel olarak yaylrlar. Bu akla ilk somut olarak gelen rnein gne olduudur. Gne dnyadan ok uzak olduundan dolay bu uzakl sonsuz olarak alabiliriz. Uzaklk sonsuz olunca gneten kan nlar dnya yzeyine parelel olarak gelmektedir. Bu tip k kaynaklarna directional light source denmektedir. Light 0 iin bu rnei komut olarak yazarsak aadaki gibi kod blounu gsterebiliriz.
GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0} glLightfv(GL_LIGHT0, GL_POSITION, light_position);

Bu yukardaki rnekte z ekseninden gelen k kayna tanmlanmtr. Drdnc parametreyi sfrdan farkl bir deere sahip olduunda bu tip k kayna positional light source olarak adlandrlr. Bunun anlam ( x, y, z ) noktasnda konumlandrlm olan bir k kaynann bulunmas anlamna gelmektedir. Bu sanki masann stne konmu olan bir lambann bulunmas gibidir.

50

Ik kaynann karakteristiklerini grdkten sonra materyallerin karakteristiklerini inceleyerek ikisi arasndaki benzerlikleri veya farkllklar anlayacaz. En ok bilinen materyal zellikleri nceden grm olduunuz k kayna zelliklerine benzemektedir. Bu zellikleri belirlemek iin kullanlan mekanizma kta kullanlan mekanizma ile benzerlik tamaktadr. Fakat bu sefer materyaller iin kullanlan komut glMaterial*() fonksiyonudur.
void glMaterial[if]v( GLenum face, GLenum pname, Type *param );

Fonksiyon sayesinde, klandrmada kullanm iin, materyalin zelliini belirler. face parametresi, GL_FRONT, GL_BACK veya GL_FRONT_AND_BACK deerlerini alarak nesnenin yz materyaline, materyaller iin tanmlanm olan zelliklerin uygulanmas anlamna gelmektedir. Bu parametreye uygulanacak deerler ise param parametresi tarafndan belirlenir. param parametresi, bir vektr veya diziyi iaret eden bir iaretidir. Bu pname parametresi iin deerler tablo 2-3 te gsterilmektedir. Tablo 2-3 glMaterial*() pname Parametresi

Parametre
GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_SHININESS GL_EMISSION

Varsayl Deerler
(0.2, 0.2, 0.2, 1.0) (0.8, 0.8, 0.8, 1.0) (0.0, 0.0, 0.0, 1.0) (0.0) (0.0, 0.0, 0.0, 1.0)

Anlam
Ambient renk Diffuse renk specular renk specular exponent emissive renk

face parametresi iin GL_FRONT olarak tanmlanm ise, GL_FRONT deeri OpenGL e poligonun sadece n ksmnda materyal zelliklerini kullanlaca anlatlmaktadr GL_BACK olduunda ise poligonun arka ksmnda materyal zelliklerinin kullanlaca veya GL_FRONT_AND_BACK kullanldnda ise poligonun her iki

51

yzeyinde bu materyal zelliklerinin geerli olaca bildirilmektedir. Program altrldnda resim 2-13 te izim yaplmaktadr.

Resim 2-13

2.28 Blending
OpenGL de renk karm ( color blending ) izeceiniz nesnelere saydamlk katlmasna izin vermektedir. Bu saydamlk sayesinde, gerek hayatta grmekte olduunuz

52

su, am, pencereler ve dier nesneleri simule edebilirsiniz. u ana kadar nesneler zerinde kullandmz renk verme fonksiyonu glColor3*() fonksiyonuydu. Fonksiyon sadece parametre almaktadr. Bu parametrelerin ne olduklarn biliyorsunuz. Nesnelere saydamlk katabilmek iin baka bir renk fonksiyonu kullanacaz. Bu fonksiyon imdiye kadar kullanlan parametreye ek olarak drdnc bir parametre almaktadr. Bu parametreye alfa parametresi denmektedir. Kullanacamz fonksiyon ise glColor4*() fonksiyonudur. Peki ya alfa deeri ne yapar ? Alfa deeri nesnenin yeni rengini, frame buffer nda bulunan renk ile birletirmektedir. Frame buffer olarak sylenen ey sistemde kullanlan tm buffer larn btndr. Yani color buffer, depth buffer, stencil buffer ve accumulation buffer size tek bir frame buffer n verebilmek iin birleirler. Buffer lar konusuyla pek ilgimiz olamayacak. Blending ileminde, RGB bileenleri fragmann rengini ve alfa bileeni ise o fragmann katlk derecesini yani effaf olmama derecesini syler. Saydam veya effaf olan cisimlerin effaf olmama derecesi saydam olmayan kilere gre daha dktr bu da demek oluyor ki bu cisimlerin alfa deerleri daha dktr.

2.29 Kaynak ve Hedef Faktrleri


Blending ilemi esnasnda, gelen fragmann renk deerleri, bu kaynak yada source olarak bilinir, hali hazrda sakl tutulan piksellerin renk deerleri, bu ise hedef yada destination olarak adlandrlmaktadr, ile btnletirilir. lk olarak kaynak ve hedef faktrlerini nasl hesaplayacanz belirlersiniz. Bu faktrler RGBA yani, krmz, yeil, mavi ve alfa, drtlleridir. Bu drtller kaynan R, G, B ve A deeri ile hedefin R, G, B ve A deerleri ile arplr. Bunu matematiksel olarak gsterirsek kaynak ya da source un RGBA deerleri ( Sr, Sg, Sb, Sa ) ve hedefin ya da destination n RGBA deerleri ise ( Dr, Dg, Db, Da ) olsun. Son olarak blending ilemi sonucunda ortaya kan deerler aadaki gibidir.

53

( Rs * Sr + Rd * Dr, Gs * Sg + Gd * Dg, Bs * Sb + Bd * Db, As * Sa + Ad * Da ) Kaynak ve hedef RGBA deerleri srasyla s ve d alt simge karakteri ile belirtilmektedir. imdi kullanacamz fonksiyon, kaynak ve hedef blending faktrlerini oluturmaktadr. Kullanacamz fonksiyonun ad glBlendFunc() tur ve bu fonksiyon iki sabiti destekler. lki hesaplanmas gereken kaynak faktr ve dieri ise hedef faltrdr. Ek olarak blending ilemini aktif hale getirmek iin her zaman aadaki tek satrlk kodu yazmalsnz.
glEnable(GL_BLEND);

Blending ilemini inaktif yapmak istiyorsanz bildiiniz gibi glDisable() fonksiyonuna GL_BLEND parametresini aktarabilirsiniz. glBlendFunc() fonksiyonun prototipi aadaki gibidir.
void glBlendFunc( GLenum sfactor, GLenum dfactor );

sfactor parametresi kaynak blending faktrnn, dfactor parametresi ise hedef blending faktrnn nasl hesaplanacan belirtirler. Bu parametreler iin mmkn deerler tablo 2-4 gsterilmektedir. Blending faktrleri 0 ile 1 aralnda deerler alr. Tabloda source, destination ve constant ( sabit ) renklerin RGBA deerleri altsimge karakteri olan s, d, c harfleri ile gsterilmektedir.

Tablo 2-4 Source ve Destinatin Blending Faktrleri

54

Sabit
GL_ZERO GL_ONE GL_DST_COLOR GL_SRC_COLOR GL_ONE_MINUS_DST_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA

lgili Faktr
source veya destination source veya destination source destination source destination source veya destination source veya destination source veya destination source veya destination source source veya destination

Hesaplanan Blending Faktr


(0, 0, 0, 0) (1, 1, 1, 1) (Rd, Gd, Bd, Ad) (Rs, Gs, Bs, As) (1, 1, 1, 1) - (Rd, Gd, Bd, Ad) (1, 1, 1, 1) - (Rs, Gs, Bs, As) (As, As, As, As) (1, 1, 1, 1) - ( As, As, As, As) (Ad, Ad, Ad, Ad) (1, 1, 1, 1)-( Ad, Ad, Ad, Ad) (f, f, f, 1); f = min(As, 1 - Ad) ( Rc, Gc, Bc, Ac) (1, 1, 1, 1) - ( Rc, Gc, Bc, Ac) (Ac, Ac, Ac, Ac) (1, 1, 1, 1) - (Ac, Ac, Ac, Ac)

GL_ONE_MINUS_SRC_ALPHA

GL_DST_ALPHA

GL_ONE_MINUS_DST_ALPHA

GL_SRC_ALPHA_SATURATE GL_CONSTANT_COLOR

GL_ONE_MINUS_CONSTANT_COLOR source veya destination GL_CONSTANT_ALPHA source veya destination

GL_ONE_MINUS_CONSTANT_ALPHA source veya destination

2.30 Basit bir rnek

55

Yapacamz rnek bir Windows uygulamasdr. Bu uygulamay GLUT yardm ile de yapabilirdik, fakat biraz deiiklik olsun istedik ve biraz da Windows uygulamalarnda altrma yapmaya altk. rnek 2-6da alfa deeri 0.75 olan ve birbirinden farkl ve kesimi iki keni gstermektedir. Blending aktif durumdadr, kaynak blending faktr GL_SRC_ALPHA olarak ve hedef blending faktr ise GL_ONE_MINUS_SRC_ALPHA olarak ayarlanmtr. Program altnda, ilk olarak sar ken pencerenin sol tarafnda izilir ve daha sonra iyan renkli ken ekrann sa tarafna izilerek kenler kesiirler. Pencerede izilecek olan ilk keni l veya r tularna basarak belirleyebilirsiniz. l tuuna bastnzda izilecek ilk ken sar renkte olan ve ekrann sol tarafna bulunan ken olacaktr, r tuuna basarsanz ekrann sa tarafna izilecek olan iyan renkli ken ilk olarak izilir. rnek 2-6
#include <windows.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glaux.h> float angle = 0.0; HDC g_HDC; BOOL fullScreen = FALSE; BOOL keyPressed[256]; int left_first = GL_TRUE; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

56

glEnable(GL_BLEND); return; } // end of void initialize(void) void resize(int width, int height) { glViewport(0, 0, (GLsizei) width, (GLsizei) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (width <= height) gluOrtho2D(0.0,1.0, 0.0, (GLfloat)height / (GLfloat)width); else gluOrtho2D(0.0, (GLfloat)width / (GLfloat)height, 0.0, 1.0); // // glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return; } // end of void resize(int, int) void draw_leftTriangle(void) { glBegin(GL_TRIANGLES); glColor4f(1.0, 1.0, 0.0, 0.75); glVertex3f(0.1, 0.9, 0.0); glVertex3f(0.1, 0.1, 0.0); glVertex3f(0.7, 0.5, 0.0); glEnd(); return; } // end of void draw_leftTrianfle(void) void draw_rightTriangle(void) { glBegin(GL_TRIANGLES); glColor4f(0.0, 1.0, 1.0, 0.75); glVertex3f(0.9, 0.9, 0.0);

57

glVertex3f(0.3, 0.5, 0.0); glVertex3f(0.9, 0.1, 0.0); glEnd(); return; } // end of void draw_rightTriangle(void) void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (left_first) { draw_leftTriangle(); draw_rightTriangle(); }else { draw_rightTriangle(); draw_leftTriangle(); } SwapBuffers(g_HDC); return; } // end of void display(void) void SetupPixelFormat(HDC hDC) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0,

58

0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; nPixelFormat = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, nPixelFormat, &pfd); return; } // end of void SetupPixelFormat(HDC) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; static HDC hDC; char string[] = "Simple Windows Application"; int width, height; switch(message) { case WM_CREATE: hDC = GetDC(hWnd); g_HDC = hDC; SetupPixelFormat(hDC); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC);

59

init(); return 0; break; case WM_CLOSE: wglMakeCurrent(hDC, NULL); wglDeleteContext(hRC); PostQuitMessage(0); return 0; break; case WM_SIZE: height = HIWORD(lParam); width = LOWORD(lParam); if (height == 0) height = 1; resize(width, height); return 0; break; case WM_KEYDOWN: keyPressed[wParam] = TRUE; return 0; break; case WM_KEYUP: keyPressed[wParam] = FALSE; return 0; break; default: break; } // end of switch(message) return DefWindowProc(hWnd, message, wParam, lParam); } // end of WndProc(HWND, UINT, WPARAM, LPARAM) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {

60

WNDCLASSEX windowClass; HWND hWnd = NULL; MSG msg; BOOL done = FALSE; DWORD dwExStyle; DWORD dwStyle; RECT windowRect; int width = 200; int height = 200; int bits = 32; windowRect.left = 0; windowRect.right = width; windowRect.top = 0; windowRect.bottom = height; windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.style = CS_HREDRAW | CS_VREDRAW; windowClass.lpfnWndProc = WndProc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = hInstance; windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = NULL; windowClass.lpszMenuName = NULL; windowClass.lpszClassName = "MyClass"; windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); if (!RegisterClassEx(&windowClass)) return 0; if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDYES) fullScreen = TRUE;

61

if (fullScreen) { DEVMODE dmScreenSettings; memset(&dmScreenSettings, 0, sizeof(DEVMODE)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { MessageBox(NULL, "Display mode failed", NULL, MB_OK); fullScreen = FALSE; } } // end of if (fullScreen) 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);

hWnd = CreateWindowEx(0,

62

"MyClass", "The OpenGL Window Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, NULL, NULL, hInstance, NULL); if (!hWnd) return 0; ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); while(!done) { PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE); if (msg.message == WM_QUIT) done = TRUE; else { if (keyPressed[VK_ESCAPE]) done = TRUE; if(keyPressed['l'] || keyPressed['L']) left_first = TRUE; if (keyPressed['r'] || keyPressed['R']) left_first = FALSE; display(); TranslateMessage(&msg); DispatchMessage(&msg);

63

} } // end of while(!done) return (int) msg.wParam; } // end of WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

izilecek olan kenlerin sras, kesitikleri blgenin rengini etkiler. Soldaki ken izildiinde, iyan fragman ( kaynak veya source ) sar fragman ile kartrlr. Tabi bu sar fragman nceden frame buffern ( hedef veya destination) iinde bulunmaktadr. Sa taraftaki ken ilk izilirse, sar iya ile kartrlcaktr. Alfa faktrnn 0.75 olmasndan dolay, kaynak iin blending faktr 0.75, hedef iin ise 1.0 0.75 = 0.25 olacaktr.

2.31 Boyutlu Nesnelerde Blending


boyutlu nesneleri saydam olarak izeceinizde, izdiiniz polgonlara bal olarak, farkl grnmler elde edebilirsiniz. izim srasn belirlerken, depth buffer n da dnmeniz gerekmektedir. Depth buffer pencere iinde bulunan nesnenin bir paras ile bak noktas arasndaki mesafeyi kontrol eder. izilecek olan nesne bak noktasna yaklatnda, bu nesne iin izilecek olan yeni renk nesne zerinde yer alr ve bu durumda nesnenin derinlik deeri depth buffer ierisinde sakl tutulur. Bu yntem ile sakl yani gzkmeyen nesnelerin paralar gereksiz yere izilmez ve blending iin kullanlmaz. Ayn ekranda saydam olan bir cisim ile saydam olmayan bir cismi beraber izmek istediinizde, saydam olmayan bir nesnenin arkasnda bulunan bir nesnenin sakl tutulan yzeyini silebilmek iin depth buffer n kullanrsnz. Eer saydam olamayan bir cismin arkasnda ister saydam olsun veya olmasn herhangi bir nesnenin paras sakl tutuluyorsa, uzak olan nesnelerin elimine edebilmek iin depth buffer na ihtiyacnz

64

olucaktr. Fakat saydam bir cisim bak noktasna daha yakn olduunda, bu cismi dier saydam olmayan cisimler ile blend etmek zorundasnz. Bunu yapabilmek iin depth buffer n read-only mofunda kullanmak gerekir. izilecek boyutlu nesnelerin izim srasda nemlidir. O zaman ilk olarak izilecek olan nesneler saydam olmayan cisimlerdir tabi bu srada depth buffer normal olarak ilemektedir. Bu depth buffer n read-only moduna getirerek, derinlik deerlerini saklayn. Saydam nesneler izildiinde, onlarn derinlik deerleri saydam olamayan nesneler tarafndan retilen deerler ile kyaslanr ve bylece saydam olan nesneler izilmez tabi bu nesneler saydam olmayan nesnelerin arkasnda iseEer saydam nesneler bak noktasna yakn olduunda, saydam olmayan nesneleri saklamazlar, nk depth buffer deerleri deimemitir. Bunun yerine bu nesneler saydam olmayan nesneler ile blend edilmitir. Depth buffer n yazlabilir olup olmadn kontrol edebilmek iin, glDepthMask() fonksiyonu kullanlr.
void glDepthMask(GLboolean flag);

flag parametresine, GL_FALSE deerini atarsanz, buffer read-only modunda olacaktr, fakat GL_TRUE olarak atarsanz yazlabilir bir buffer olacaktr. rnek 2-7, bize bu anlattklarmzn kk bir uygulamasn gsterecek bir program kodunu anlatmaktadr. Ekran ierisinde bir grid zerinde bulunan saydam ve krmz renkli bir kp ile onun biraz tesinde bulunan mavi renkli bir kre izilmitir ve bu izilen nesneler y ekseni etrafnda dnmektedir. rnek 2-7
#include <stdlib.h> #include <GL/glut.h> #include <GL/glu.h> GLfloat cube_ambient[] = {0.23, 0.0, 0.0, 1.0}; GLfloat cube_diffuse[] = {0.44, 0.0, 0.0, 1.0};

65

GLfloat cube_specular[] = {0.33, 0.33, 0.52, 1.0}; GLfloat cube_emission[] = {0.0, 0.0, 0.0, 0.0}; GLfloat cube_shininess = 50; GLfloat sphere_ambient[] = {0.0, 0.0, 0.39, 1.0}; GLfloat sphere_diffuse[] = {0.0, 0.47, 0.5, 1.0}; GLfloat sphere_specular[] = {0.0, 0.64, 0.34, 1.0}; GLfloat sphere_emission[] = {0.0, 0.0, 0.2, 0.0}; GLfloat sphere_shininess = 38; GLfloat rotate_y = 0.0; void draw_net(GLfloat size, GLint LinesX, GLint LinesZ) { int xc, zc; glBegin(GL_LINES); for (xc = 0; xc < LinesX; xc++) { glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / 2.0); glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / -2.0); } // end of for (xc = 0; xc < LinesX; xc++) for (zc = 0; zc < LinesZ; zc++) { glVertex3f( size / 2.0, 0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); glVertex3f( size / -2.0,

66

0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); } // end of for (zc = 0; zc < LinesZ; zc++) glEnd(); return; } // end of void draw_net(GLfloat, GLint, GLint) void init(void) { GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0}; glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return; } // end of init(void) void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION);

67

glLoadIdentity(); gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 2.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); return; } // end of void reshape(GLfloat, GLfloat) void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rotate_y, 0.0, 1.0, 0.0); glPushMatrix(); glTranslatef(1.0, 0.5, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, sphere_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, sphere_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, sphere_specular); glMaterialfv(GL_FRONT, GL_EMISSION, sphere_emission); glMaterialfv(GL_FRONT, GL_SHININESS, &sphere_shininess); glutSolidSphere(0.5, 16, 16); glPopMatrix();

glPushMatrix(); glTranslatef(-1.0, 0.5, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT,

68

cube_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, cube_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, cube_specular); glMaterialfv(GL_FRONT, GL_EMISSION, cube_emission); glMaterialfv(GL_FRONT, GL_SHININESS, &cube_shininess); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glutSolidCube(1.0); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix();

glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 1.0); draw_net(5, 11, 11); glEnable(GL_LIGHTING); glPopMatrix(); glutSwapBuffers(); return; } // end of void display(void) void rotate(void) { rotate_y += 0.5; if (rotate_y > 360.0) rotate_y -= 360.0;

69

glutPostRedisplay(); return; } // end of rotate_teapot(void) void keyboard(unsigned char key, int x, int y) { switch(key) { case 'R': case 'r': rotate_y = 0; glutPostRedisplay(); break; case 27: exit(0); } return; } // end of void keyboard(unsigned char, int, int) int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 400); glutInitWindowPosition(100, 100); glutCreateWindow("Teapot"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutIdleFunc(rotate); glutMainLoop(); return 0; } // end of int main(int, char**)

70

Aadaki resim 2-14, rnek 2-7 deki kodu altrdnzda ortaya kacak sonucu gstermektedir.

Resim 2-14

2.32 Bitmap Dosyalar


leride aklayacamz texture mapping de, kullancamz resim dosyalarnn ad bitmap resim dosyalardr. Bu dosyalarn uzantlar bmp olarak bilinmektedir. Bitmap dosyalarnda yada BMP dosyalarndaki en byk ey, Windows iletim sistemini kullanan bir kiinin bu dosyalar yaratabilir, ieriini deitirebilir ve gzlenebilir olmasdr. BMP dosyalar herhangi bir sktrma emalarn kullanmazlar bu sebepten dolay boyutlarnda kk bir byme gzkebilir. Fakat sktrma emasndan yoksun olmann anlam bu dosya formatnn kolaylkla okunabilir ve kullanlabilir olmasdr.

71

Resim 2-15 bir BMP dosyasnn yapsn gstermektedir. Bitmap file header, Bitmap information header ve bitmap data

Bitmap File Header Bitmap Information Header ( Palet Veri)

Bitmap Data
Resim 2-15 Bitmap dosya Bitmap File Header dosyasn yklemek iin kullanlan veri yaps BITMAPFILEHEADER dr ve bu yap aada gsterilmektedir.
typedef struct tagBITMAPFILEHEADER { WORD WORD WORD bfType; // specifies the file type; must be BM (0x4D42) // specifies the size in bytes of BMP file // reserved; must be zero // reserved; must be zero DWORD bfSize;

bfReserved1; bfReserved2;

DWORD bOffBits; } BITMAPFILEHEADER;

// specifies the ofset, in bytes, from

// BITMAPFILEHEADER stracture to the bitmap bits

Bu yap ile ilgili olarak, bir bmp dosyas ykleyeceiniz zaman dosyann uzants-

72

na dikkat etmeniz gerektiidir. Bunu, dosyann BITMAPFILEHEADER yapsnn bir yesine bakarak yani bfType e bakarak dosyann uzantsnn bmp olup olmadn anlayabilirsiniz. Bu ye bitmap dosyalar iin her zaman 0x4D42 deerine eittir. Bu sayy nceden Windows proglamlamas esnasnda grmtnz. Bir bmp uzantl dosyay aarken bu say ile kontrol yaplmaktadr. bfSize, bize dosyann boyutunu, bOffBits ise bize dosyann bandan itibaren Bitmap Datann nereden baladn ieren bir ofset bilgisini gsterir. Bir sonraki inceleyeceimiz veri blgesi, her BMP dosyasna zg olan bilgileri ierir. Bu blge, BMP dosyasnn 8-bitlik ve bir palet verisine sahip olmasna gre bir veya iki paraya ayrlmaktadr. Biz palet verisi ile ilgilenmeyeceimiz iin sadece BITMAPINFOHEADER yapsn okuyacaz.
typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG LONG WORD WORD // number of bytes required by the structure biWidth; // width of the bitmap, in pixels biHeight; // height of the bitmap, in pixels biPlanes; // number of color planes, must be 1 biBitCount; // number of bits per pixel must be 1, 4, 8, // 16, 24, 32 DWORD biCompression; // type of compression DWORD biSizeImage; // size of image in bytes LONG LONG biXPelsPerMeter; // number of pixels perm eter in x-axis biYPelsPerMeter; // number of pixels perm eter in y-axis

DWORD biClrUsed; // number of colors used by the bitmap DWORD biClrImportant; // number of colors that are important } BITMAPINFOHEADER;

Bu yapnn yanndaki aklamalar okumak kendini aklayacak kadar yeterlidir. Burada nemli olan bir BMP dosyasn nasl bellee ykleyeceimizdir. BMP dosyasnn Bitmap Data ksmnda krmz ve mavi renk deerlerinin yerleri deimitir yani dosya bildiiniz gibi krmz, yeil ve mavi olarak sral deilde mavi, yeil krmz ola-

73

rak okunmal ve krmz ile mavi deerlerin yerlerinin deimesi gerekmektedir. Bu ilem, dosya okunurken yaplmadr. Bir bitmap dosyas yaratlacaksa bu ilemi tersinden yapmak yani ncelikle mavi sonra yeil ve en son olarak krmz renk deeri dosyaya yazlmaldr nk bitmap dosya yapsna uymamz gerekir. rnek 2-8 de 24-bitlik bir bitmap dosyasn ykleye ve bitmap dosyasn oluturan program kodu ve onun balk dosyas bulunmaktadr. rnek 2-8 Bitmap.h ve Bitmap.c
// Bitmap.h #ifndef _BITMAP_H #define _BITMAP_H #include <windows.h> typedef unsigned char *BITMAPIMAGE; #define BITMAP_ID 0x4D42 #define FILE_NOT_OPENED_TO_WRITE -12 extern BITMAPIMAGE Bitmap_LoadBitmapFile(const char*, const BITMAPINFOHEADER*); extern int Bitmap_WriteBitmapFile(const char*, LONG, LONG, BITMAPIMAGE); #endif // Bitmap.c #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Bitmap.h"

BITMAPIMAGE

74

Bitmap_LoadBitmapFile(const char* filename, const BITMAPINFOHEADER* bitmapInfoHeader) { FILE *filePtr; BITMAPFILEHEADER bitmapFileHeader; BITMAPIMAGE bitmapImage; DWORD imageIdx; unsigned char tempRGB; if ((filePtr = fopen(filename, "rb")) == NULL) { MessageBox(NULL, "File not found.", "Error", MB_OK); return NULL; } fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr); if (bitmapFileHeader.bfType != BITMAP_ID) { MessageBox(NULL, "Invalid file extention.", "Error", MB_OK); fclose(filePtr); return NULL; } fread((BITMAPINFOHEADER*)bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr); fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET); bitmapImage = (BITMAPIMAGE) malloc(bitmapInfoHeader->biSizeImage); if (!bitmapImage) { MessageBox(NULL, "Out of memory", "Error", MB_OK); fclose(filePtr);

75

return NULL; } fread((BITMAPIMAGE)bitmapImage, sizeof(*bitmapImage), bitmapInfoHeader->biSizeImage, filePtr); if (!bitmapImage) { MessageBox(NULL, "File not read.", "Error", MB_OK); free(bitmapImage); fclose(filePtr); return NULL; } for(imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3) { tempRGB = bitmapImage[imageIdx]; bitmapImage[imageIdx] = bitmapImage[imageIdx + 2]; bitmapImage[imageIdx + 2] = tempRGB; } fclose(filePtr); return bitmapImage; } int Bitmap_WriteBitmapFile(const char* filename, LONG width, LONG height, BITMAPIMAGE imageData) { FILE *filePtr; BITMAPFILEHEADER bitmapFileHeader; BITMAPINFOHEADER bitmapInfoHeader;

76

DWORD imageIdx; unsigned char tempRGB; if ((filePtr = fopen(filename, "wb")) == NULL) return FILE_NOT_OPENED_TO_WRITE; bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER); bitmapFileHeader.bfType = BITMAP_ID; bitmapFileHeader.bfReserved1 = 0; bitmapFileHeader.bfReserved2 = 0; bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfoHeader.biPlanes = 1; bitmapInfoHeader.biBitCount = 24; bitmapInfoHeader.biCompression = BI_RGB; bitmapInfoHeader.biSizeImage = width * height * 3; bitmapInfoHeader.biXPelsPerMeter = 0; bitmapInfoHeader.biYPelsPerMeter = 0; bitmapInfoHeader.biClrImportant = 0; bitmapInfoHeader.biWidth = width; bitmapInfoHeader.biHeight = height; for(imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx += 3) { tempRGB = imageData[imageIdx]; imageData[imageIdx] = imageData[imageIdx + 2]; imageData[imageIdx + 2] = tempRGB; } fwrite((BITMAPFILEHEADER*)&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr); fwrite((BITMAPINFOHEADER*)&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);

77

fwrite((BITMAPIMAGE) imageData, sizeof(*imageData), bitmapInfoHeader.biSizeImage, filePtr); fclose(filePtr); return 0; }

2.33 Texture Mapping


Texture mapping konusu OpenGL de ok geni bir konudur, bu yzden sadece gerekli olan ksmlar inceleyeceiz. Texture mapping, poligonlar zerine resimleri yaptrmanz salamaktadr. Mesela, bir kre yarattnz ve bu kre stne 3 boyutlu olarak bir dnya resmi yatrabilirsiniz. Texture mapping i tm 3 boyutlu oyunlarda grebilirsiniz ve bu method oyulara daha ok gereklik katmaktadr. Texture mapleri veriyi tutan kare dizilerinden olumaktadr. Her veri parasna texel denmektedir. Bunlar veriyi tayan kare dizileri plmalarna karn, texture mapleri karesel olmayan nesneler zerine map edilebilirler, mesela silindirler ve kreler gibi Tasarmclar genellikle, kendi grafik almalarnda iki boyutlu texture mapping yntemini kullanrlar. Fakat tek boyutlu ve boyutlu texture kaplamalar da mevcuttur, fakat biz bunlar ile ilgilenmeyeceiz. Konu olarak basit bir ekilde iki boyutlu texture mappingi inceleyeceiz.

2.34 ki Boyutlu Texture


Bir dosyadan, texture mapping iin kullanacanz bir dosyay bellee ykledikten sonra, bunu texture map olarak tantmanz gerekmektedir. Texture map in boyutlar bu ii yapabilmeniz iin hangi fonksiyonlar kullanacanz belirtmektedir. Eer 2 bo-

78

yutlu bir texture map ilemi yapmak istiyorsanz glTexImage2D() fonksiyonunu kullann. Bir boyutlu texture map ilemi yapmak istiyorsanz glTexImage1D() fonksiyonunu, boyutlu olarak ilem yapmak istiyorsanz glTexImage3D() fonksiyonunu kullanabilirsiniz.
void glTexImage2D(GLenum target, GLint level, GLint intenalFormat, GLsizei width, GLsizei height, GLint border, GLenum type, const GLvoid* texels);

target parametresi GL_TEXTURE_2D veya GL_PROXY_TEXTURE_2D olarak ayarlanabilir. Fakat bizim iin bu parametreyi GL_TEXTURE_2D yapmak daha uygundur. level parametresi texture map in znrln belirler. Sadece tek bir znrlk kullanmak istiyorsanz bu parametreyi 0 yapn. u an iin bir ok znrlk modunun kullanmn tartmayacaz. internalFormat paramtresi 1 den 4 e kadar veya size gsteremiyeceimiz 38 sabit deerden birini kullanan sayya eittir. Bizim sadece kullanabileceklerimiz GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB ve GL_RGBA olmaktadr. width ve height parametreleri texture map in genilik ve boyutunu belirlerler. Bu deerler 2 nin ss bir deer olmaldrlar. border parametresi texture evresinde bir snrn olup olmadn bildirmektedir. Snr var ise bu deer 1, yok ise deer 0 olmaldr. format parametresi, texture mapin verisinin formatn tanmlar ve bu format GL_COLOR_INDEX, GL_RGB, GL_RGBA, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE veya GL_LUMINANCE_ALPHA olabilir. type parametresi ise bu verinin tipini belirtir ve GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT veya GL_UNSIGNED_FLOAT olabilir. Son parametre olan texel parametresi bir iaretidir. Bu iareti texture mapping iin kullanacanz resmi iaret eder. Mesela bir RGBA resmi yklediniz ve onu gsteren iareti ise textureData olsun. Bu dizinin boyutu textureWidth ve textureHeight olsun. glTexImage2D() fonksiyonu ise aadaki gibi kullanlabilir.

79

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

2.35 Texture Nesneleri


Texture nesneleri, texture verilerini saklamanza ve onlar kullanmak iin hazr durumda bekletmenizi salamaktadr. Bu nesneleri kullanarak, bir kerede bir ok texture yi bellee ykleyebilir ve izim esnasnda bunlarn herhangi birine referans verebilirsiniz. Texture nesnelerini kullanamak iin ilk yapacanz ey bir texture ismi yaratmanzdr. Texture isimleri sfrdan farkl iaretsiz bir tamsaylardr. Ayn texture ismini iki kere kullanmamak iin glGenTextures() fonksiyonunu kullann.
void glGenTextures(GLsizei n, GLuint *textureNames);

parametre n, ka tane texture ismi yaratlacan bildirmektedir ve bu isimle bir dizinin iine yerletirilecek olan bir textureNames parametresinin gsterdii dizi olacaktr. rnek olarak vermek gerkirse, texture isimlerini saklayacanz bir 3 elemanl diziniz mevcutsa, fonksiyon aadaki gibi kullanlacaktr.
unsigned int textureNames[3]; ... glGenTextures(3, textureNames);

Texture isimlerini yarattktan sonra bu isimlerin texture verilerine verilmesi veya balanmas gerekmektedir. Bunu glBindTexture() fonksiyonu ile gerekletirebilir.
void glBindTexture(GLenum target, GLuint textureName);

Bu fonksiyonu ilk olarak kullandnzda, yeni bir texture nesnesi varsayl deerlere sahip olarak yaratlr. OpenGL bu isim balama ileminden sonra texture nesnesinde-

80

ki varsayl deerleri yeniden tanmlayacaktr. target parametresi bu fonksiyon iin GL_TEXTURE_1D, GL_TEXTURE_2D veya GL_TEXTURE_3D olabilir. Bu isim balama ileminden sonra texture nesnesini o an kullanlabilecek texture durumuna getirmek iin glBindTexture() fonksiyonunu kullann. Mesela birka texture nesnesi yarattnz dnelim ve bu nesnelerin texture verilerini ve texture zelliklerini bu nesnelere baladnz. Ekranda poligonlar izeceiniz zaman, glBindTexture() ile texture belirleyerek, OpenGL e belirlemi olduunuz texture syleyebilirsiniz. Aadaki kod paras, texture zellikleri ayarlandktan sonra, ikinci texture nesnesini current texture olacan, OpenGL e anlatmaktadr.
unsigned int textureNames[3]; ... glGenTextures(3, textureNames); ... glBindTexture(GL_TEXTURE_2D, textureNames[1]); // texture verisi ve zelliklerini ayarla glBindTexture(GL_TEXTURE_2D, textureNames[1]); // nesneyi iz

2.36 Texture Filitreleme


Texture resimleri, poligonlara uygulandktan sonra, biimi bozuk hale dnr ve sonu olarak kk bir piksel texel in sadece kk bir parasn veya texel leri gsterebilir. Resmin son hali iin, OpenGL e bu pikselleri ve texel lerin nasl hesaplanacan texture filitreleme kullanarak anlatabilirsiniz. Texture filitrelemede, magnification, bir pikselin bir texel parasn gstermesi anlamn tamaktadr ve minification ise bir pikselin texel leri gstermesi anlamna gelir. OpenGL e bu her iki durumu nasl ele almak istediinizi glTexParameter() fonksiyonunu ararak anlatabilirsiniz.

81

void glTexParameter(GLenum target, GLenum pname, GLint param);

target parametresi kullandnz texture boyutuna baldr ve GL_TEXTURE_1D, GL_TEXTURE_2D veya GL_TEXTURE_3D deerleri alabilir. Magnification filitrelemede pname parametresi GL_TEXTURE_MAG_FILTER deerini ve minification filitrelemede pname parametresi GL_TEXTURE_MIN_FILTER deerini almaktadr. param parametresinin alaca deerler tablo 2-5 te gsterilmektedir. Tablo 2-5 Texture Filitre Deerleri

Filitre
GL_NEAREST

Aklama
Texture edilecek olan pikselin merkezine en yakn olan texel i kullanr. izilecek olan pikselin ne en yakn olan texellerin arlkl ortalamasn kullanr.

GL_LINEAR merkezi-

GL_NEAREST_MIPMAP_NEAREST

GL_NEAREST filitrelemeyi ve poligon znrlne en yakn imaj kullanr. GL_LINEAR filitrelemeyi ve poligon znrlne en yakn imaj kullanr. GL_NEAREST filitrelemeyi ve poligon znrlne en yakn olan iki mipmap ler arasdaki arlkl ortalamay kullanr. GL_LINEAR filitrelemeyi ve poligon znrlne en yakn olan iki mipmap ler arasdaki arlkl ortalamay kullanr.

GL_NEAREST_MIPMAP_LINEAR

GL_LINEAR_MIPMAP_NEAREST

GL_LINEAR_MIPMAP_LINEAR

82

2.37 Texture Fonksiyonlar


OpenGL, texture fonksiyonlar aracl ile texture map renklerinin davrann belirler. Her texture iin, glTexEnvi() fonksiyonu ile drt tane texture fonksiyonundan seim yapabilirsiniz.
void glTexEnvi(GLenum target, GLenum pname, GLint param);

target parametresi GL_TEXTURE_ENV deerine eit olmaldr. pname parametresine ise GL_TEXTURE_ENV_MODE deerini aktararak, frame buffer ndaki renkler ile texture lerin nasl birletirileceini belirleyebilirsiniz. param parametresi iin kullanlacak deerler tablo 2-6 da belirtilmitir. Tablo 2-6

Mod
GL_BLEND GL_DECAL GL_MODULATE

Aklama
Texture rengi piksel rengi ile arplr ve sabit bir renk ile birletirilir. Texture, mevcut olan pikseller ile yer deitirir. Texture rengi piksel rengi ile arplr.

glTexEnvi() ini varsayl deeri GL_MODULATE tir. Aadaki tek satrlk kod texture fonksiyonunu GL_DECAL e ayarlamaktadr.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

Ekrannz izdiinizde, her verteksin texture koordinatlarn belirtmeniz gerekir.

83

Texture koordinatlar, bir nesneye ait olan texture map in her bir texel i nereye konumlanacan belirtmek iin kullanlr. Bir texture koordinat olan ( 0, 0 ) texture un sol alt kesini, ( 1, 1 ) ise sa st kesini belirtir. ki boyutlu texture lerde bu koordinatlar ( s, f ) formundadr.Burada s ve f deerleri 0 dan 1 e doru deiir. Resim 2-16 poligonun her verteksi iin texture koordinatlarn gstermitir. Bu koordinatlar her verteks render edilmeden nce, kendileri ile ilikilendirilmi olan texture koordinatlar belirlenmelidir.

( 0.0, 1.0 )

( 1.0, 1.0 )

( 0.0, 0.0 )

( 1.0, 0.0 )

Resim 2-16 Texture koordinatlarn glTexCoord*() fonksiyonu ile belirlersiniz. Biz konu ierisinde iki boyutlu texture mapping yapacamzdan dolay bu fonksiyonun aadaki iki boyutlu olann kullanacaz.
void glTexCoord2f(GLfloat s, GLfloat t);

Aada bu fonksiyonun basit bir kullanmn gstermektedir.


glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-0.5, 0.5, 0.5); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, 0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(0.5, 0.5, -0.5);

84

glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, 0.5, -0.5); glEnd();

Texture mapping konusu bu kadar rnek ise Windows platformunda geekletirilmi olan dnen kpn bir benzeri vardr fakat bu rnek GLUT ktphanesi fonksiyonlar kullanlarak yaplmtr. Bu kbn her bir yzeyine bir bitmap dosyasndan yklenmi resim yaptrlmtr. Resim ise satran tahtasna benzeyen bir resim kbn her yzeyi texture kaplama yaplmtr. Kb, farenizin sol tuuna bask tutarak dndrebilirsiniz. Fareyi hareket halinde iken serbest braktnzda kb sabit bir hzda dnmeye devam edecektir. rnek 2-9' u inceleyiniz. rnek 2-9
#include <windows.h> #include <stdlib.h> #include <GL/glut.h> #include "Bitmap.h" #include "HiResTimer.h" #define BITMAP_ID 0x4D42 BITMAPINFOHEADER bitmapInfoHeader; BITMAPIMAGE bitmapData = NULL; unsigned int texture; int last_x, last_y; rotationY = 0.0, timeElapsed = 0.0; GLfloat dx = 0.0, dy = 0.0; HiResTimer timer = NULL;

GLfloat rotationX = 0.0,

85

void DrawTextureCube(GLfloat xPos, GLfloat yPos, GLfloat zPos) { glPushMatrix(); glTranslatef(xPos, yPos, zPos); glBegin(GL_QUADS); // top face glTexCoord2f(0.0, 0.0); glVertex3f(-0.5, 0.5, 0.5); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, 0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(0.5, 0.5, -0.5); glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, 0.5, -0.5); glEnd(); glBegin(GL_QUADS); // front face

glTexCoord2f(0.0, 0.0); glVertex3f(0.5, -0.5, 0.5); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, 0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(-0.5, 0.5, 0.5); glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, -0.5, 0.5); glEnd(); glBegin(GL_QUADS); // right face

glTexCoord2f(0.0, 0.0); glVertex3f(0.5, 0.5, -0.5); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, 0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(0.5, -0.5, 0.5);

86

glTexCoord2f(0.0, 1.0); glVertex3f(0.5, -0.5, -0.5); glEnd(); glBegin(GL_QUADS); // left face

glTexCoord2f(0.0, 0.0); glVertex3f(-0.5, -0.5, 0.5); glTexCoord2f(1.0, 0.0); glVertex3f(-0.5, 0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(-0.5, 0.5, -0.5); glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, -0.5, -0.5); glEnd(); glBegin(GL_QUADS); // bottom face

glTexCoord2f(0.0, 0.0); glVertex3f(0.5, -0.5, 0.5); glTexCoord2f(1.0, 0.0); glVertex3f(-0.5,-0.5, 0.5); glTexCoord2f(1.0, 1.0); glVertex3f(-0.5, -0.5, -0.5); glTexCoord2f(0.0, 1.0); glVertex3f(0.5, -0.5, -0.5); glEnd(); glBegin(GL_QUADS); // back face

glTexCoord2f(0.0, 0.0); glVertex3f(0.5, 0.5, -0.5); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, -0.5, -0.5); glTexCoord2f(1.0, 1.0); glVertex3f(-0.5, -0.5, -0.5); glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, 0.5, -0.5); glEnd(); glPopMatrix();

87

return; } // end of void DrawTextureCube(GLfloat, GLfloat, GLfloat) void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glEnable(GL_TEXTURE_2D); bitmapData = Bitmap_LoadBitmapFile("Checkerboard_64.bmp", &bitmapInfoHeader); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); return; } // end of void initialize(void) void reshape(int width, int height) {

88

glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)width/(GLfloat)height, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return; } // end of void resize(int, int) void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBindTexture(GL_TEXTURE_2D, texture); glTranslatef(0.0, 0.0, -3.0); glRotatef(rotationY, 0.0, 1.0, 0.0); glRotatef(rotationX, 1.0, 0.0, 0.0); DrawTextureCube(0.0, 0.0, 0.0); glDisable(GL_TEXTURE_2D); glPopMatrix(); glFlush(); glutSwapBuffers(); return; } // end of void display(void) void spin(void) { rotationX += dx; rotationY += dy;

89

if (rotationX > 360.0) rotationX -= 360.0; if (rotationY > 360.0) rotationY -= 360.0; glutPostRedisplay(); return; } // end of void spin(void) void mouse(int button, int button_state, int x, int y ) { if ( button == GLUT_LEFT_BUTTON && button_state == GLUT_DOWN ) { glutIdleFunc(NULL); if (last_x == x) dx = 0.0; if (last_y == y) dy = 0.0; last_x = x; last_y = y; } // end of if statement else glutIdleFunc(spin);

return; } // end of void mouse(int, int, int, int)

void motion(int x, int y ) { timeElapsed = HiResTimer_GetElapsed_Seconds(timer); rotationX += (float) (y - last_y); rotationY += (float) (x - last_x);

90

dx = (float)(y - last_y)/(1000*timeElapsed); dy = (float)(x - last_x)/(1000*timeElapsed); if (rotationX > 360.0) rotationX -= 360.0; if (rotationY > 360.0) rotationY -= 360.0; last_x = x; last_y = y; glutPostRedisplay(); return; } // end of void motion(int, int) void keyboard(unsigned char key, int x, int y) { switch(key) { case 27: case 'q': exit(0); default: break; } // end of switch(key) return; } // end of void keyboard(unsigned char, int, int) int on_exit(void) { free(bitmapData); bitmapData = NULL; free(timer); timer = NULL;

91

return 0; } // end of void on_exit(void) int main(int argc, char** argv) { timer = HiResTimer_Create(); if (!HiResTime_Init(timer)) { MessageBox(NULL, "Timer initialization failed", 0, 0); free(timer); timer = NULL; exit(-1); } // end of if (!HiResTime_Init(timer)) glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("Texture Mapping Application"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMotionFunc( motion ); glutMouseFunc( mouse ); _onexit(on_exit); glutMainLoop(); return 0; } // end of int main(int, char**)

Resim 2-17, bu kodu altracanz zaman, texture mapping ile kaplanm olan kb gstermektedir.

92

Resim 2-17 Kodu inceledikten sonra, kod ierisinde birka bilinmedik fonksiyon grceksiniz. Bunlardan biri glPixelStorei() fonksiyonudur. Bu fonksiyonu aklamadan nce birka sylenecek ey var. Gelitirmi olduunuz bir projeyi bir makineden dier bir makineye tayorken, projeniz daha yava alr. Bununla ilgili bir ok faktr olmasna ramen, bu faktrlerden ilgineceimiz sadece biri olan hafzadaki alignment' tr. Baz makinelerde veri aktarm daha hzl yaplsn diye, veri 2, 4 veya 8 byte'lk snrlar erevesinde memoride doru bir pozisyonda konumlanr. Bu durumda, glPixelStorei() fonksiyonunu kullanarak, veri pozisyonunu (data alignment) kontrol edebilirsiniz.
void glPixelStorei(GLenum pname, Type param);

Fonksiyonu kullanmak iin, pname parametresi GL_PACK_ALIGNMENT veya GL_UNPACK_ALIGNMENT olabilir. param parametresi 1, 2, 4 veya 8 olabilir. pname parametresini GL_PACK_ALIGNMENT olarak belirlediinizde, OpenGL' e ve-

93

rinin nasl paketleneceini anlatrsnz. GL_UNPACK_ALIGNMENT parametresini kullandmzda, OpenGL' e verinin hafzada nasl paketlenmeyecei anlatlr. lk olarak grdnz dier fonksiyonlar zaman ile ilgili olan fonksiyonlardr. HiResTimer.h balk dosyas bu fonksiyonlarn tanmlamasn yapmaktadr. Zaman ile ilgili fonksiyonlar niin kullandmz ve bu fonksiyonlarn ne ie yaradn anlatalm. Zaman, dnyada bir niteliktir, kendi oyun dnyanzda ise bu zaman kavram bir nem tamaktadr. Zaman dikkatli bir ekilde izleyebilmek iin bir timer kullnrsnz. Bu timer fiziksel hesaplamalara daha ok gereklik kazandrr ve hesaplamalar, izim esnasndaki her izilen ereveden ( frame ) bamsz bir ekilde takipedebilirsiniz. ki tip timer kullanabilirsiniz: Yksek performansa sahip olan bir timer veya Windows' un mesaj olarak gnderdii timer, WM_TIMER. Bu ikisi arasndaki en nemli fark hz ve doruluktur. Biz yksek performansa sahip olan timer' kullancaz nk hza ve dorulua sahiptir. Eer bilgisayarnz bunu desteklemiyorsa, bunun yerine WM_TIMER' kullann. Yksek perfomanstaki timer' kullanabilmek iin makinenizde bir saniyede ka clock atldn belirlemeniz gerekmektedir. Bundan sonra o anki zaman renip, uygulamanzn ne zaman baladn gsteren bir deikenin iine bu zaman saklamanz gerekir. Bu her bir tasla gerekletirmek iin QueryPerformanceFrequency() ve QueryPerformanceCounter() fonksiyonlarn kullanmalsnz.
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

QueryPerformanceFrequency() fonksiyonu bir saniyede ka clock atldn gstermektedir. Clock saysn lpFrequency iaretisi aracl ile elde ederiz. Donanmnz bu fonksiyonu desteklemiyorsa, bu iaretinin gsterecei deer sfr olabilir ve fonksiyondan dnen deer sfr' dr. Eer donanmnz bu fonksiyonu destekliyorsa fonksiyondan dnen deer sfrdan farkl olacaktr. QueryPerformanceCounter() ise o anki

94

timer' n current deerini dnderir ve dnen deer lpPerformanceCount iaretisi tarafndan gsterilmektedir. Bu fonksiyonun donanm tarafnda desteklenip desteklenmemesi gibi durumunda fonksiyonun izledii tutum, QueryPerformanceFrequency() fonksiyonunun izledii durumdan farksz olacaktr. Her iki fonksiyon da ayn paramere tiplerini almaktadrlar. Bu parametre tipi 64-bitlik integer olarak ifade edilir ve ismi LARGE_INTEGER' dr.
typedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }; LONGLONG QuadPart; } LARGE_INTEGER;

LowPart alan 32-bitlik low-order parasn ve HighPart ise 32-bitlik high-order parasn belirtmektedir. QuadPart ise 64-bitlik iaretli bir tam sayy gsterir. Dikkat edeceiniz gibi bu veri yaps bir union' dur. rnek 2-10, HiResTimer.h balk dosyasn ve HiResTimer.c ise bu balk dosyasndaki fonksiyonlarn gerekletirimlerini gstermektedir. rnek 2-10
// HiResTimer.h #ifndef _HIRESTIMER_H #define _HIRESTIMER_H #define WIN32_LEAN_MEAN #include <windows.h> struct _HIRESTIMER; typedef struct _HIRESTIMER* HiResTimer;

95

extern HiResTimer HiResTimer_Create(void); extern void HiResTimer_Destroy(HiResTimer*); extern BOOL HiResTime_Init(HiResTimer); extern float HiResTimer_GetElapsed_Seconds(HiResTimer); extern float HiResTimer_GetFPS(HiResTimer, unsigned int); extern float HiresTimer_LockFPS(HiResTimer, unsigned char); #endif // HiResTimer.c #include <windows.h> #include <stdio.h> #include <stdlib.h> #include "HiResTimer.h" struct _HIRESTIMER { LARGE_INTEGER m_StartTime; LARGE_INTEGER m_ticksPerSecond; LARGE_INTEGER s_lastTime_GetElapsed_Seconds ; LARGE_INTEGER s_lastTime_GetFPS; LARGE_INTEGER s_lastTime_LockFPS; }; HiResTimer HiResTimer_Create(void) { HiResTimer _this; _this = (HiResTimer) malloc(sizeof(struct _HIRESTIMER)); if (!_this) { MessageBox(NULL, "\tOut of memory", "Error", 0); return NULL; } // end of if (!_this) return _this; } /* end of HiResTimer HiResTimer_Create(LARGE_INTEGER, LARGE_INTEGER)

96

*/ void HiResTimer_Destroy(HiResTimer *_this) { free(*_this); *_this = NULL; return; } // end of void HiResTimer_Destroy(HiResTimer*) BOOL HiResTime_Init(HiResTimer _this) { if (!QueryPerformanceFrequency( &(_this->m_ticksPerSecond))) return FALSE; else { QueryPerformanceCounter(&(_this->m_StartTime)); _this->s_lastTime_GetElapsed_Seconds = _this->m_StartTime; _this->s_lastTime_GetFPS = _this->m_StartTime; _this->s_lastTime_LockFPS = _this->m_StartTime; return TRUE; } } // end of BOOL HiResTime_Init(HiResTimer) float HiResTimer_GetElapsed_Seconds(HiResTimer _this) { LARGE_INTEGER currentTime; float seconds; QueryPerformanceCounter(&currentTime); seconds = ((float)currentTime.QuadPart (float)_this->s_lastTime_GetElapsed_Seconds.QuadPart) / (float)_this->m_ticksPerSecond.QuadPart; _this->s_lastTime_GetElapsed_Seconds = currentTime; return seconds;

97

} // end of float HiResTimer_GetElapsed_Seconds(HiResTimer) float HiResTimer_GetFPS(HiResTimer _this, unsigned int elapsedFrames) { LARGE_INTEGER currentTime; float fps; QueryPerformanceCounter(&currentTime); fps = (float)elapsedFrames* (float)_this->m_ticksPerSecond.QuadPart / ((float)currentTime.QuadPart (float)_this->s_lastTime_GetFPS.QuadPart); _this->s_lastTime_GetFPS = currentTime; return fps; } /* end of float HiResTimer_GetFPS(HiResTimer, unsigned int) */ float HiresTimer_LockFPS(HiResTimer _this, unsigned char targetFPS) { LARGE_INTEGER currentTime; float fps; if (targetFPS == 0) targetFPS = 1; do { QueryPerformanceCounter(&currentTime); fps = (float) _this->m_ticksPerSecond.QuadPart /

98

((float)(currentTime.QuadPart _this->s_lastTime_LockFPS.QuadPart)); }while(fps > (float)targetFPS); _this->s_lastTime_LockFPS = currentTime; return fps; } /* end of float HiresTimer_LockFPS(HiResTimer, unsigned char) */

HiResTimer_Create() fonksiyonu sizin iin bir timer yaratr ve dndrecei deer HiResTimer olan bir iareti dnderecektir. Bu iareti yaratlan timer' gstermektedir. HiResTimer_Destroy() ise yarattnz timer' yok eder, alaca parametre ise bu yok edilecek olan timer' n iaretisidir. Bu iaretinin gsterdii timer' n ii boaltlp iaretiye NULL deeri atanmaktadr. HiResTime_Init() fonksiyonu timer' ilklemektedir. Bu ilkleme ileminde, bir saniyede atlan clock says ve o anki balang clock deeri bulunur. HiResTimer_GetElapsed_Seconds() fonksiyonu, bize fonksiyonun arlmasndan bu yana nekadar saniyenin getiini dndrmektedir. Dn deeri float tipindedir. HiResTimer_GetFPS(), elapsedFrames parametresi zerinden ortalama nekadar frame' in gsterildiini sylemektedir. HiresTimer_LockFPS() fonksiyonu ise istenilen frame says kadar frame orann kilitleyerek bekletir. Bu istenilen frame says targetFPS parametresi ile fonksiyona aktarlmaktadr.

99

You might also like