Nakładanie tekstur
Tekstury w OpenGL dzielą się na:
Jednowymiarowe 1D - jest to jedna linia pikseli(jej wysokość to jedna linia, a szerokość to liczba pikseli tekstury lub na odwrót)
Dwuwymiarowe 2D - jest to normalny dwuwymiarowy obrazek(posiada wysokość Y i szerokość X)
Rozmiar tekstury musi być potęgą 2 tzn. zarówno wysokość jak i szerokość w przypadku
tekstur dwuwymiarowych. Maksymalny rozmiar tekstur określony jest możliwościami karty. Np. stare karty 3D typu VOODOO 1 mogą obsługiwać tekstury maksymalnie o rozmiarze 256x256.
Inne możliwe wówczas rozmiary to:
4x4,8x8,16x16,32x32,64x64,128x128
Nowsze karty oferują oczywiście o wiele większe rozmiary tekstur jak np. 1024x1024 co związane jest z ilością pamięci podręcznej akceleratora. Aby obsłużyć tak duże tekstury należy mieć odpowiednie sterowniki i biblioteki do OpenGL. W współczesnych nam czasach możliwe jest też umieszczanie tekstur w pamięci operacyjnej komputera co odciąża pamięć karty, a to dzięki zastosowaniu interfejsu AGP.
Algorytm nakładania tekstury na prymityw jest następujący:
Wczytujemy do pamięci obraz tekstury. W tym celu wykorzystujemy procedurę:
AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL;
if (!Filename)
{
return NULL;
}
File=fopen(Filename,"r");
if (File)
{
fclose(File);
return auxDIBImageLoad(Filename);
}
return NULL;
};
która zwraca adres załadowanej bitmapy(pliku typu BMP którego nazwę przekazano w zmiennej "Filename"). Najważniejszym rozkazem w tej procedurze jest "auxDIBImageLoad" który ładuje obraz i zwraca do niego adres tzn. do struktury załadowanego obrazu. Jednym z pól tej struktury jest jego nazwa, obraz, wielkość, szerokość itp... Cały proces załadowania tekstury i ustalenia jej parametrów realizuje poniższa procedura:
int LoadGLTextures()
{
int Status=FALSE;
AUX_RGBImageRec *TextureImage[1];
memset(TextureImage,0,sizeof(void *)*1);
if (TextureImage[0]=LoadBMP("Data/Crate.bmp"))
{
Status=TRUE;
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[0])
{
if (TextureImage[0]->data)
{
free(TextureImage[0]->data);
}
free(TextureImage[0]);
}
Tworzy ona jedną zmienną "TextureImage" typu AUX_RGBImageRec. Będzie to struktura do której zostanie załadowany obraz BMP. Linia:
memset(TextureImage,0,sizeof(void *)*1);
czyści tę strukturę zerami.
Kolejna ważna linia to:
glGenTextures(1, &texture[0]);
"generuje" jedną(1) teksturę przekazując do zmiennej "texture[0]" tupu Gluint numer dostępowy do tworzonej tekstury.
Kolejna linia:
glBindTexture(GL_TEXTURE_2D, texture[0]);
ustawia jako bieżącą teksturę(dalsze operacje dotyczące tekstur będą dotyczyć bieżącej tekstury) teksturę o numerze dostępowym zawartym w "texture[0]". Tekstura ta będzie traktowana jako tekstura 2D(GL_TEXTURE_2D).
Linia:
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
ustala parametry bieżącej tekstury. Składnia polecenia glTexImage2d jest następująca:
glTextImage2D(Glenum target, Glint level, Glint components, GLSize width, Glsize height, Glint border, Glenum format, Glenum type, const Glvoid *pixels);
gdzie :
target - określa rodzaj tekstury (tu GL_TEXTURE_2D)
level - wskazuje poziom szczegółów obrazu tekstury (zwykle jest równy 0) - tzn. poziom mipmappingu
components - określa ilość składowych koloru użytych dla każdego piksela(1,2,3,4 - są to kolejno R,G,B,A).
width - szerokość obrazu tekstury
height - wysokość obrazu tekstury
Uwaga: Wielość tekstury musi spełniać równanie:
2^n + 2(ilość pikseli ramki)
gdzie:
n - to wysokość lub szerokość
border - ilość pikseli ramki. (0 lub 1)
format - format koloru(GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA)
type - format danych reprezentujących każdy piksel(tj. ile bitów, czy liczba stało lub zmienno przecinkowa itp...- GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP,
GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT )
data -> bufor gdzie znajduje się obraz tekstury
Znaczenie niektórych stałych dotyczących określania formatu koloru:
GL_COLOR_INDEX - 8 bitowy
GL_RGB - 24bitowy
GL_RGBA - 24bitowy + kanał ALFA(przezroczystości)
GL_UNSIGNED_BYTE - bajt bez znaku
GL_UNSIGNED_SHORT - liczba dwubajtowa bez znaku
Kolejne linie to:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
też ustalają parametry bieżącej tekstury tzn. w jaki sposób tekstura będzie nakładana na obiekt. Składnia poleceń typu "glTexParametri" jest następująca:
void glTexParameterf(Glenum target, Glenum pname, Glfloat param );
gdzie: jako wartość podajemy liczbę typu Glfloat
void glTexParameteri(Glenum target,Glenum pname,Glint param );
gdzie: jako wartość podajemy liczbę typu Glint
Opis parametrów:
target - typ tekstury(np. GL_TEXTURE_2D)
pname - nazwa ustalanego parametru
param - wartość nadawana parametrowi "pname"
Opis niektórych parametrów "pname":
GL_TEXTURE_MIN_FILTER - jak tekstura będzie traktowana gdy jej rozmiar okaże się większy od prymitywa na który zostanie nałożona. Dopuszczalne wówczas wartości parametru to:
GL_LINEAR - uśrednianie pikseli czyli tekstura będzie rozmywana
GL_NEAREST - piksele będą zwielakratniane czyli tekstura bez rozmycia tak jak w starszych grach typu DOOM
GL_TEXTURE_MAG_FILTER - jak tekstura będzie traktowana gdy jej rozmiar okaże się mniejszy od prymitywa na który zostanie nałożona. Dopuszczalne wówczas wartości parametru to:
GL_LINEAR - uśrednianie pikseli czyli tekstura będzie rozmywana
GL_NEAREST - piksele będą zwielakratniane czyli tekstura bez rozmycia tak jak w starszych grach typu DOOM
GL_TEXTURE_BORDER_COLOR - kolor tekstury w formacie RGBA np. (0,0,0,0)
GL_TEXTURE_WRAP_S - określa czy nasza tekstura będzie zawijana wzdłuż osi X na
obiekcie jeśli jego rozmiar będzie większy od tekstury(czyli zwielakratniana). Wartości:
GL_REPEAT - tak
GL_CLAMP - nie(tekstura będzie rozciągana wzdłuż osi X)
GL_TEXTURE_WRAP_T - określa czy nasza tekstura będzie zawijana wzdłuż osi Y na
obiekcie jeśli jego rozmiar będzie większy od tekstury(czyli zwielakratniana). Wartości:
GL_REPEAT - tak
GL_CLAMP - nie(tekstura będzie rozciągana wzdłuż osi Y)
i inne...
Innym ważnym poleceniem jest glTextEnvi które też określa sposób w jaki nasza bieżąca tekstura zostanie wyświetlona na ekranie .Jego składnia:
void glTexEnvi( Glenum target, Glenum pname, Glint param )
gdzie:
target - musi być GL_TEXTURE_ENV
pname - nazwa ustalanego parametru
param - wartość nadawana parametrowi "pname" typu Glfint
Opis niektórych parametrów:
GL_TEXTURE_ENV_MODE - określa sposób w jaki każdy piksel tekstury zostanie przeniesiony na ekran. Wartości:
GL_DECAL - każdy piksel jest żywcem przenoszony na ekran bez dodatkowych operacji. Przy tym trybie światła mimo iż są włączone nie są uwzględniane.
GL_MODULATE - każdy piksel jest poddawany działaniu światła i przenoszony na ekran. GL_MODULATE ustawione jest domyślnie.
...
UWAGA! Aby OpenGL wyświetliło tekstury typu 2D w procedurze inicjującej "InitGL" należy dodać linię:
glEnable(GL_TEXTURE_2D);
A jeśli chcemy aby tekstury 2D nie były wyświetlane w programie dajemy:
glDisable(GL_TEXTURE_2D);
Posiadając tak przygotowaną już teksturę można ją użyć w procedurze rysującej scenę np. do narysowania teksturowanego trójkąta co demonstruje poniższy kod:
glTranslatef(0.0f,0.0f,-6.0f);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_TRIANGLES);
glTexCoord2f(0.1f, 0.0f);
glVertex3f(0.0f,0.0f,0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.0f,0.0f,0.0f);
glTexCoord2f(0.1f, 1.0f);
glVertex3f(0.0f,-2.0f,0.0f);
glEnd();
Opis tego fragmentu kodu:
Rozkaz glBindTexture opisany wcześniej ustala bieżącą teksturę którą będziemy nakładać na trójkąt. Rozkaz glTexCoord2f ustala jaki punkt tekstury ma odpowiadać kolejnemu definiowanemu przez polecenie glVertex wierzchołkowi. Składnia tego polecenia jest następująca:
glTexCoord2f( Glfloat s, Glfloat t )
gdzie:
s - współrzędna X typu Glfloat
t - współrzędna Y typu Glfloat
S i T są liczbami z zakresu [0,1]. Gdzie np.
S T
(0,0) - lewy dolny róg tekstury
(1,0) - prawy dolny róg tekstury
(0,1) - lewy górny róg tekstury
(1,1) - prawy górny róg tekstury
(0.5,0) - środek od dołu tekstury
(0.5,1) - środek od góry tekstury
itd...(dozwolone są też wartości pośrednie w postaci ułamków)
więc np. kod:
glTexCoord2f(0.1f, 0.0f);
glVertex3f(0.0f,0.0f,0.0f);
przypisuje wierzchołkowi (0.0f,0.0f,0.0f) punkt bieżącej tekstury określony przez współrzędne (0,0) czyli jej górny lewy róg. To właśnie rozkaz typu glTexCoord pozwala na nałożenie pojedynczej tekstury na nawet skomplikowany obiekt - wtedy tekstura dzielona na części. Każda taka część tekstury nakładana jest na odpowiadający jej fragment obiektu z zachowaniem odpowiedniej kolejności itp..
Uwaga: Można łączyć teksturę i cieniowanie kolorem[rozkaz glColor3f() itd...] co pozwoli na uzyskanie odpowiedniego zabarwienia tekstury(w ten sposób obserwator będzie mieć wrażenie, że widzi kilka różnobarwnych tekstur mimo iż będzie to tylko jedna zabarwiana z oddzielna przez OpenGL). Natomiast zastosowanie np. rozkazu:
glColor3f(1.0f,1.0f,1.0f);
powoduje iż definiowane po nim wielokąty nie będą miały w ogóle żadnego zabarwienia - tzn. będą miały zabarwienie zgodne z barwą nakładanej na nie tekstury. Rozkaz ten potrzebny jest do wyłączenia zabarwiania tekstur.
Należy zauważyć, że możliwość zabarwiania tekstury określonym kolorem możliwa jest o ile zmienna "GL_COLOR_MATERIAL" ustawiona jest na TRUE co realizuje polecenie:
glEnable(GL_COLOR_MATERIAL);
Jeśli chcemy wyłączyć zabarwianie kolorem teksturę dajemy:
glDisable(GL_COLOR_MATERIAL);
[Patrz plik LESSON6.RAR w przykładach]
Wyszukiwarka
Podobne podstrony:
T 14Rzym 5 w 12,14 CZY WIERZYSZ EWOLUCJIustawa o umowach miedzynarodowych 14 00990425 14foto (14)DGP 14 rachunkowosc i audytPlakat WEGLINIEC Odjazdy wazny od 14 04 27 do 14 06 14022 14 (2)index 14Program wykładu Fizyka II 14 15więcej podobnych podstron