8 - realtime programlamaya giriş = kaplama / texture mapping / normal mapping

8 - realtime programlamaya giriş = kaplama / texture mapping / normal mapping

chrome_nickel

biraz ara verdiydik. devam edelim.

3d ortamda nesnelerimizi normalde renk dolgusu ile doldurabiliyorduk. zaten, dolgu yapmadan bir 3d kütle sadece hayali bir koordinat cöpü. ancak her zaman nesnelerimizi homojen renkle kaplamak bize yetmeyebilir. özellikle bilgisayar oyunları gibi yüksek performansın hat safhada önemli olduğu uygulamalarda her detayı modelle halledemeyiz. çok basit veya gölge tonları çok seçilemeyecek detayları modellemek yerine kaplama yaparak çözebiliriz. bir resmi, 3d kütlenin üzerine kaplayarak modelin tam kırmızı şerit çizgisi geçmesi gereken yere kırmızı resimdeki kırmızı şerit çizgiyi oturtarak çözebiliriz... tamam bu en doğru yol. ama.... kırmızı şeritin modelin tam istediğimiz yerine gelmesini nasıl sağlayacağız!?

işte buna mapping denir. yani haritalamak. modelin bir haritasını alırsınız. ve kaplamanızı buna göre hazırlarsınız ( photoshop yada herhangi diğer resim editörlerinde ). ardından yazılımınıza haritaya göre kaplamayı nasıl yapacağını yazılım, modelin haritasına göre resmi çekiştirir ezer büker deforme edip poligonların üzerine doğru şekilde yayar. işte buna texture mapping denir. şimdi, bunun nasıl yapıldığını bir iki resimle açıklayalım. kodlamasını sonra yapıcaz. önce mantığını öğrenmek gerek.

şekil-1´de resimlerin koordinat sistemleri görünmekte

windows´ta resimlerin koordinatları, resmin üst sol köşesinden başlarken opengl´de resimlerin koordinatları sol alt köşeden başlar ( tamam diceksiniz niye standart bişi yapmıyorlar? bu da yazılım tekelciliği değil, 2d ortamda koordinatları sol üst köşeden hesaplamak matematiksel olarak daha kolayken 3d ortamda sol alt köşeden hesaplamak daha kolaydır. zaten 3d ortam uzay koordinat sistemine dayandığından, uzay koordinat sistemi de sol alt köşeyi baz alır.

bu durumda, şekil-1´deki resmi gene şekil-1´deki poligona tam oturmuş şekilde kaplamak isteseydik koordinatları şu şekilde belirlememiz gerekirdi

vertex - 1´in kaplama koordinatları = 0.0 , 1.0
vertex - 2´nin kaplama koordinatları = 0.0 , 0.0
vertex - 3´ün kaplama koordinatları = 1.0 , 0.0
vertex - 4´ün kaplama koordinatları = 1.0 , 1.0


şimdi bunun ne anlama geldiğine bakalım.
vertex -1´in kaplama koordinat´ı 0.0 ve 1.0 oluyor. ilk değer resmin x koordinatı. ikinci değer resmin y koordinatı.

yani vertex - 1 üzerine resmin x yönünde 0.0 ve 1.0 koordinatlarına denk gelen pixeli oturtulacak. ( sol üst köşeye denk geliyor )

vertex -2´ye resim x yönünde 0.0 ve y yönünde 0.0 koordinatları oturtulacak. ( sol alt köşeye denk geliyor.)

vertex -3´e x yönünde 1.0 ve y yönünde 0.0 koordinatlarındaki pixel´i oturtulacak. ( resmin sağ alt köşesi )

vertex 4´ü yorumlamaya gerek yok sanırım

resmin ebatları ne olursa olsun sol alt köşesi daima x=0.0 ve y=1.0´dır

sağ üst köşesi de x=1.0 ve y=1.0´dır

bütün kaplamaları buna göre yaparız.

mesela, modelin bir vertexinin üstüne, kaplama resminin tam ortası gelsin istiyor isek, x= 0.5 y=0.5 yazmalıyız, modelin bir vertex´inin tam üstüne resmin sol kenarının tam ortası gelsin istersek, x=0.0 y=0.5 yazmalıyız, modelin bir vertexinin üstüne resmin üst kenarının ortası gelsin istersek, x=0.5 y=1.0 yazmalıyız.

bu sanırım texture mapping konusunu açıklamak için yeterlidir.

en kısa zamanda bir kaplama resmini opengl ile nasıl yükleyebiliriz ve bunu modelimize nasıl uygulayabiliriz, bunun uygulamasını yapıcaz.

2006-09-10 03:13:48

Cvp

chrome_nickel

Opengl ile Texture Mapping, yani nesneleri kaplamak.

ilk bilmemiz gereken şey, opengl´de kaplamalar bir liste şeklinde saklanır. biz bu listeye göre kaplamalarımızı modellerimizde kullanırız.

önce kaplama resmimizin liste numarasını bellekte tutacak bir değişken lazım

int kaplama;

sonradan kaplamayı yüklerken ve oluştururken, opengl kaplama listesinden bir numara ayırıcaz, ve bu numarayı da kaplama isimli değişkenimize atayıp iyi bir kaplama veritabanı kurmuş olucaz.

şimdi kaplamaya başlayalım.

AUX_RGBImageRec tipi, opengl´nin tanıdığı bir çeşit resim formatıdır diyebiiriz.

AUX_RGBImageRec *kaplama_resmi;

şeklinde bir tanım yaparak, opengl formatında yeni bir resim oluşturuyoruz.

kaplama_resmi=auxDIBImageLoad("kaplama/dosyası/yolu.dosya");

tanımı ile de bitmap dosyamızı, opengl formatındaki, kaplama_resmi dosyamıza atamış oluyoruz.

glGenTextures(1, &kaplama);
bu tanım ile de, opengl´de kaplama listesinden 1. sırayı ayırtıp, bunu kaplama isimli değişkenimizle ilişkilendiriyoruz.

glBindTexture(GL_TEXTURE_2D, kaplama);

kaplama kaplamasının GL_TEXTURE_2D tipinde bir kaplama olacağını belirtiyoruz.

glTexImage2D(GL_TEXTURE_2D, 0, 3, kaplama_resmi->sizeX, kaplama_resmi->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, kaplama_resmi->data);

burdan da, kaplama isimli kaplamada kullanılacak olan daha önceden opengl formatında ayarlanmış doku resmini belirtiyor ve opengl´nin kullanabilmsei için ebatlarını ve verisini gösteriyoruz.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // küçültme
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR ); // büyütme


kaplamalar, 3d ortamda kaplanırken, bazen büyütülür yada küçültülür. böyle durumlarda resmi filtrelemek ve yeniden ebatlandırmak gerekir. işte bu iki tanımda da küçültürken hangi filtreyi, büyütürken hangi filtreyi kullanacağını belirtiyoruz.

küçültme filtreleri:
GL_NEAREST
GL_LINEAR
GL_NEAREST_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR_MIPMAP_LINEAR

//---------------------------------------------
büyütme filtreleri :
GL_NEAREST
GL_LINEAR


bunları yaptıktan sonra, kaplamamız sadece opengl veritabanında tanımlanmış oluyor.

daha sonradan, bir nesneyi kaplamadan önce
glEnable(GL_TEXTURE_2D);
ile 2d kaplamaları aktif hale getirmeliyiz.
kaplamaları aktif hale getirdikten sonra
glBindTexture(GL_TEXTURE_2D, kaplama);
komutu ile, opengl veritabanına kaydettiğimiz kaplamalardan hangini kullanacağımızı belirtiyoruz.

glBegin(GL_POLYGON);
glColor3f(1.0,1.0,1.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-10,10,0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-10,-10,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(10,-10,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(10,10,0);
glEnd();


glTexCoord2f(kaplama_x_koordinatı, kaplama_y_koordinatı);
her vertex´den önce o vertexin resmin hangi koordinatına denk geleceğini belirliyoruz. böylece resmin o kısmı çekiştirilerek modelin ilgili vertex´i üstüne yerleştiriliyor.

bütün profesyonel 3d yazılımları zaten normal mapping ve uvw mapping ile, her vertex için bir kaplama koordinatı belirliyor. bizde onlardan alacağımız dosya formatlarından oyuna 3d objemizi yükleyeceğimiz için, dosya içindeki her vertex için atanmış kaplama koordinatları sayesinde, bu koordinatlarla uğraşmayız. zaten saçma olur :).. onun yerine dosyadan okuyup modelin değişkenine otomatik olarak yükleyen bir döngü yazarız ve olay biter.

ilgili konunun çalışan kodları, atelyedeki ChromiGL başlığında 1.1 sürümünde.


unutmamanız gereken bir konu , resimlerin bellekte çok yer kaplayacağı. 32bit bitmap formatındaki bir resimde her pixel için 32 bitlik bir alan ayrılacağıdır.

512x512 pixellik bir resmin, bellekte ne kadar yer kaplayacağına bakalım.

8bit = 1byte
1024byte = 1kb
1024kb = 1mb

32/8=4 byte. bir pixel 4 byte tutuyormuş.
512x512 = 262144 pixel varmış.
262144x4=1048576 byte tutuyor
1048576/1024 = 1024 kb tutuyormuş. o da 1mb eder.

demekki 512x512 ebatlarındaki bir kaplama ram´de 1mb yer kaplayacak. o halde yapacağımız oyunda kullanacağımız kaplamaların tamamını ele alıp hesaplayarak nekadar bellek tuttuklarını görebilir, ve uygulamanın çalışacağı sistemi göz önünde bulundururarak kaplama resimlerinin boyutlarına karar verebiliriz ( yada karar vermeliyiz )

2006-09-10 03:13:48