750 likes | 880 Views
Wprowadzenie do grafiki komputerowej. Tekstury I. Scena z Quake 3 bez tekstur. Scena z Quake 3 z teksturami. Inny przykład nakładania tekstur. Dodawanie szczegółów dzięki teksturom. Pomysł polega na tym, żeby zamiast licznych wielokątów, użyć obrazów do urozmaicenia powierzchni.
E N D
Wprowadzenie do grafiki komputerowej Tekstury I
Scena z Quake 3 bez tekstur Tekstury
Scena z Quake 3 z teksturami Tekstury
Inny przykład nakładania tekstur Tekstury
Dodawanie szczegółów dzięki teksturom • Pomysł polega na tym, żeby zamiast licznych wielokątów, użyć obrazów do urozmaicenia powierzchni
I jeszcze jeden Tekstury
Ogólne podejście do teksturowania Przestrzeń tekstury 2D (u,v) lub 3D (u,v,w) 2D (s,t) lub 3D (s,t,r) Przestrzeń obiektu 3D (x,y,z) Przestrzeń ekranu 2D (x,y) Tekstury
y z x Mapowanie tekstur 2D – zasady mapowania obiekt geometryczny w 3D ekran t W ogólności stosujemy przekształcenie typu: x = X (s,t); y = Y (s,t); z = Z (s,t); tekstura - zawsze zapisana na prostokącie s Tekstury
Zasady mapowania, c.d. + = geometria obraz Nałożona tekstura Stałe pytanie: jak przypisać punkty z obrazu punktom na obiekcie?
Sposób mapowania wcale nie jest jednoznaczny. planarcubiccylindricalrectangularcylindrical (Paul Bourke: http://paulbourke.net/texture_colour/tiling/ również: http://paulbourke.net/texture_colour/ )
Dygresja: algorytm mapowanie na sferę(spokojnie można pominąć) Załóżmy: jest kątem od osi X (0<=<=2) jest kątem od osi Z (0 <= <=) Parametryczne równanie sfery wygląda: Z równania na Z mamy: t = / = arccos (Z/R) / Z równania na X mamy: s = [arccos ( X/R sin ( t) ) ] / 2 gdzie: = arccos x => x = cos Zatem jeśli znamy współrzędne punktu na powierzchni sfery, X, Y, Z, możemy obliczyć odpowiadający mu punkt (s,t) w przestrzeni tekstury. Tekstury
Rodzaje mapowania: rozwinięcie powierzchni [Piponi2000]
Option: make an atlas charts atlas surface Sander2001: TextureMapping Progressive Meshes
Na co zwracamy uwagę przy mapowaniu tekstur? • Na transformację kształtu • Na transformację barwy Tekstury
Definiowanie tekstury Przez teksturę rozumiemy tablicę (przede wszystkim 2D, ale także 1D i 3D) zawierającą w każdym elemencie od jednej do czterech danych (jasność lub składowe koloru (R, G, B, A)). Element tekstury określany jest jako texel OpenGL od wersji 1.2 obsługuje tekstury 3D. Niektóre rozszerzenia (np. SGIS_texture4D) pozwalają na użycie tekstur 4D Tekstury
Pierwszy przykład z ręcznie definiowaną teksturą (z czerwonej książki) static Glubyte checkImage[checkImageHeight][checkImageWidth][4]; int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } } Tekstury
Tekstura z określoną jedną składową (kolor lub luminancja) static Glubyte checkImage[checkImageHeight][checkImageWidth]; int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j] = (GLubyte) c; } } Tekstury
Wczytywanie obrazków jako tekstur FREEGLUT niestety nie ma odpowiedniej funkcji. GLTools dostarcza funkcji do ładowania formatu targa (.tga) Można też wykorzystać jedną z innych licznych dostępnych funkcji (podręczniki OpenGL, www,…) Można posłużyć się alternatywnym do GLUTa interfejsem, np. CPW, GLFW (opisane na stronie www.opengl.org) i pewnie wieloma innymi. Ostatecznie taka funkcja rezerwuje obszar, do którego wpisuje obrazek wczytany z pliku, i zwraca adres obszaru. Tekstury
Podstawowy schemat użycia… • W zasadzie nadaje się do obsługi jednej tekstury i obejmuje etapy: • Wyspecyfikowanie tekstury: • wczytanie lub wygenerowanie tablicy pikseli • poinformowanie OpenGL, że tablica jest teksturą • Przypisanie współrzędnych tekstury wierzchołkom obiektu • Określenie parametrów mapowania • powielanie tekstury, filtrowanie Tekstury
ETAP 1 - definiowanie tekstury 2D glTexImage2D • Najważniejsza procedura: glTexImage2Dtworzy teksturę na podstawie wskazanej tablicy. • Niestety ma dosyć rozbudowaną listę parametrów. • Na szczęście zwykle nie ma potrzeby wykorzystywania pełnych możliwości budowania listy. • Obok glTexImage2Dmamy też funkcje glTexImage1D i glTexImage3D Tekstury
glTexImage2D c.d. voidglTexImage2D(GLenumtarget, GLintlevel, GLintinternalFormat, GLsizeiwidth, GLsizeiheightGLintborder, GLenumformat, GLenumtype, void*pixels); Wartości i znaczenia parametrów: targetGL_TEXTURE_2D(i na razie nie ma innych możliwości) level0przy pojedynczej teksturze – mipmappinglevel internalFormatokreśla, które składowe koloru będą wykorzystane przy mieszaniu kolorów (tabelka na następnym slajdzie) width szerokość tekstury w pikselach heightwysokość tekstury w pikselach borderszerokość obramowania tekstury w pikselach (0 lub 1) formatformat, w jakim zapisana jest tablica tekstury typetyp elementu tablicy tekstury (np. GL_UNSIGNED_BYTE)*pixelswskaźnik do tablicy zawierającej teksturę Tekstury
Parametry glTexImage2D internalFormat: liczba od 1 do 4 określa, które składowe tekstury (format tekseli) będą użyte przy nakładaniu i mieszaniu kolorów: W OpenGL internalFormat może przyjąć wartości 38 stałych symbolicznych, ale nie ma gwarancji, że konkretna realizacja to zinterpretuje je poprawnie. W praktyce wystarczy ograniczyć się do powyższych czterech wartości. Tekstury
Dygresja Przeliczanie RGB na Luminance, czyli na jasność obrazu monochromatycznego. Nie ma jednoznacznej reguły, ale często stosowana zależność jest następująca: L = .3*red + .59*green + .11*blue Tekstury
Parametry glTexImage2D • width, height - szerokość i wysokość tekstury • Tekstury NIEmuszą być kwadratowe. Obecnie ich wymiary NIE muszą być potęgami 2 (jak było do wersji 2.0) – choć wydaje się, że ciągle tak jest bezpieczniej. • Minimalnyzagwarantowanyrozmiartekstury 2D: 1024x1024 (kiedyś było mniej) • borderma znaczenieprzyłączeniukawałkówteksturiinterpolacjisklejonychbrzegów. Teoretycznie – bo obecnie ustawiamy go tylko na 0 Tekstury
Parametry glTexImage2D • GLenumformat • Określa format danych, w jakich podawany jest obraz tekstury: • GL_RGB, GL_RGBA, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA • GLenumtype • Określa typ danych w teksturze: • GL_UNSIGNED_BYTE, GL_SHORT, GL_BYTE, GL_INT… Tekstury
Nowość: glCopyTexImage1D/2D • W bieżącej wersji OpenGL można również pobierać tekstury z bufora obrazu. • Postać funkcji:voidglTexImage1D(GLenumtarget, GLintlevel, GLintinternalFormat, GLsizeix, GLsizeiy,GLintwidth, GLenumborder); lubvoidglTexImage1D(GLenumtarget, GLintlevel, GLintinternalFormat, GLsizeix, GLsizeiy,GLintwidth, GLintheight, GLenumborder); Tekstury
Tekstury jako obiekty • Począwszy od wersji 1.1 w OpenGL można efektywniej zrządzać teksturami, traktując je jako obiekty. • Wykorzystujemy do tego dwie funkcje: • glGenTextures - pozwala określić wskaźnik do tekstury traktowanej jako obiekt, oraz • glBindTexture - kojarzy konkretną (wybraną) teksturę z obiektem. Tekstury
Tekstury jako obiekty Potraktowanie tekstur jako obiektów pozwala na załadowanie do pamięci większej liczby tekstur i szybkie przełączanie między nimi. Można (i należy) je stosować wszędzie tam, gdzie mamy do czynienia z rozbudowaną sceną z wieloma teksturami Tekstury
Przygotowanie: nadanie teksturom identyfikatorów Przygotowanie tekstur jako obiektów wykonujemy przez wywołanie: void glGenTextures(GLsizei n, GLuint *textures) n: liczba tekstur textures: wskaźnik do tablicy, do której będą wpisane liczby oznaczające identyfikatory tekstur . W ten sposób nadajemy teksturom identyfikatory (liczby całkowite dodatnie – ale nie musimy tego wiedzieć). Tekstury
glGenTextures() Przykład wywołania. unsigned int textureNames[3]; ... glGentextures(3, textureNames); tworzy trzy nowe identyfikatory tekstur. Tekstury
Dowiązanie tekstur W następnym kroku należy dowiązać (bind) identyfikator tekstury (jako obiektu) do danych tekstury (obrazka): voidglBindTexture(GLenumtarget,GLuinttexture) target:GL_TEXTURE_1D, GL_TEXTURE_2D , GL_TEXTURE_3D, (od wersji 1.2) … i jeszcze 6 innych wartości, którymi zajmiemy się później texture: numer tekstury – dowiązuje teksturę Od tego momentu wszystkie funkcje ładujące i ustalające parametry dotyczą tylko dowiązanej tekstury. Tekstury
Filtrowanie tekstur: glTexParameter() Filtrowanie określa w jaki sposób tekstura będzie nakładana na obiektoraz jak będzie się zmieniać przy zmianie położenia obiektu względem obserwatora. W OpenGL realizuje się je za pomocą funkcji glTexParameter()w różnych wariantach: voidglTexParameterf(GLenumtarget, GLenumpname, GLfloatparam); voidglTexParameteri(GLenumtarget, GLenumpname, GLintparam); voidglTexParameterfv(GLenumtarget, GLenumpname, GLfloat*params); voidglTexParameteriv(GLenumtarget, GLenumpname, GLint*params); Tekstury
Filtrowanie tekstur: glTexParameter() Pierwszy parametr target może przyjmować następujące wartości:target: { GL_TEXTURE_1D |GL_TEXTURE_2D | GL_TEXTURE_3D } co jest zrozumiałe, oraz dodatkowo {GL_TEXTURE_CUBE_MAP | GL_TEXTURE_RECT} które omówimy później. Drugi parametr, pname, wyznacza o jaki rodzaj filtracji chodzi. W wersji 3.3 dopuszcza się 16 różnych wartości. My rozważymy teraz tylko kilka. Trzeci parametr podaje konkretne parametry filtracji. Tekstury
Tekstura Wielokąt Tekstura Wielokąt Powiększenie – jeden teksel jest mapowany na wiele pikseli Pomniejszenie – wiele tekseli jest mapowanych na jeden piksel Filtrowanie tekstur – pierwsze zastosowanie Pierwsze zastosowanie: Ustalenie algorytmu interpolacji przy powiększaniu/pomniejszaniu obiektów Tekstury
Filtrowanie tekstur – powiększanie, pomniejszanie • pname: GL_TEXTURE_MAG_FILTER| GL_TEXTURE_MIN_FILTER • param: • GL_NEAREST (Point Sampling) • Wybierz teksel, którego środek jest najbliższy danemu pikselowi • GL_LINEAR (Bilinear Sampling) • Użyta jest ważona średnia tablicy 2x2 najbliższych tekseli • W przypadku mipmappingu mamy do dyspozycji więcej trybów interpolacji. Tekstury
Filtrowanie tekstur: powiększanie i pomniejszanie Przykład: 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_RGBA, checkImageWidth,checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); GL_NEARESTmoże być zastąpione przez GL_LINEAR Tekstury
t s tekstura Drugie zastosowanie filtrowania tekstur: powtarzanie i rozciaganie (GL_REPEAT i GL_CLAMP) pname: GL_TEXTURE_WRAP_S| GL_TEXTURE_WRAP_T param: GL_REPEATGL_CLAMPGL_CLAMP_TO_EDGEGL_CLAMP_TO_BORDERGL_MIRRORED_REPEAT… i jeszcze trochę… GL_REPEAT GL_CLAMP Tekstury
Filtrowanie tekstur: powtarzanie i rozciąganie Tryb GL_REPEAT jest znacznie bardziej popularny Tekstury
Przykład (fragment) // Tablica siedmiu obiektów - tekstur GLuint tList[7]; … // Możemy (choć nie musimy) nadać obiektom identyfikatory enum Texture_Objects { XRAY = 0, LIGHTNING, FALL, COINS, SAND, STORM, MARBLE }; … // Wygeneruj identyfikatory dla 7 tekstur: glGenTextures(7, tList); // Dowiąż pierwszy obiekt glBindTexture(GL_TEXTURE_2D, tList[XRAY]); // Ustaw parametry mapowania i załaduj teksturę glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); LoadBMP("xray.bmp");… Tekstury
Kontynuacja przykładu W analogiczny sposób możemy doładować kolejne tekstury. W ten sposób wszystkie tekstury stają się potencjalnie dostępne Dla porządku:Funkcja LoadBMP wykonuje w środku, po wczytaniu obrazka, glTexImage2D – informując OpenGLa, że obrazek będzie teksturą. Przed nałożeniem określonej tekstury na obiekt należy ponownie wywołać glBindTexture, z wybranym numerem tekstury. Można powiedzieć, że pierwsze wywołanie glBindTexture, wraz z dalszymi ustaleniami, odpowiada definicji funkcji, a kolejne – wywołaniom funkcji. Tekstury
Tekstury rezydentne PYTANIE:Gdzie umieszczone są załadowane tekstury? OpenGL stara się w miarę możliwości umieszczać tekstury w wysokowydajnej pamięci karty graficznej. Tekstury
Przestrzeń tekstury Przestrzeń obiektu t 1, 1 (s, t) = (0.2, 0.8) 0, 1 A a c (0.4, 0.2) b B C (0.8, 0.4) s 0, 0 1, 0 Jak działają współrzędne tekstury? • Przestrzeń tekstury 2D jest określona parametrycznie, zmiennymi (s, t) z przedziału [0,1] (zazwyczaj). Tekstury
Nadawanie współrzędnych tekstury – podejście uproszczone • Klasa GLBatch w GLTools dostarcza funkcji, które umożliwiają bezpośrednie łączenie pojedynczych współrzędnych tekstury z pojedynczymi wierzchołkami. • Styl tutaj podany nie jest zalecany, jest mało efektywny, ale prosty. Nawiązuje do starego stylu OpenGL. • Wykorzystujemy funkcje:Vertex3f – do wskazania konkretnego wierzchołkaMultiTexCoord2f – do wskazania odpowiadającej współrzędnej teksturyi dodatkowoNormal3f – podającej normalną w wierzchołku, do wyliczenia oświetlenia. Tekstury
Nadawanie współrzędnych tekstury Każdy wielokąt jest określony przez współrzędne obiektu i współrzędne tekstury. Współrzędne obiektu opisują gdzie wielokąt umieszczony jest na scenie. Współrzędne tekstury opisują współrzędne tekseli. Można je wyznaczyć np. funkcją MultiTexCoord()z klasy GLBatch w GLTools: MultiTexCoord2f(texture_layer, coord) texture_layer– warstwa tekstury (na początek 0) coords– współrzędne tekstury s, t, w tekselach Tekstury
Współrzędne tekstury (GLTools) Możemy ręcznie łączyć współrzędne tekstury i wierzchołków obiektu. objectBatch.Begin(GL_TRIANGLES, …); objectBatch.MultiTexCoord2f(0, 0.0, 0.0); objectBatch.Vertex3f(-1.0, -1.0, 0.0); objectBatch.MultiTexCoord2f(0, 0.0, 1.0); objectBatch.Vertex3f(-1.0, 2.0, 0.0); objectBatch.MultiTexCoord2f(0,1.0,1.0); objectBatch.Vertex3f(2.0, 2.0, 0.0); objectBatch.End(); Współrzędne tekstury powinny poprzedzać współrzędne wierzchołka (podobnie jak przy podawaniu współrzędnych wektora normalnego, parametrów materiałowych, etc.). Tekstury
Uaktywnienie nakładania tekstur Przed rozpoczęciem nakładania tekstur na obiekty należy uaktywnić obsługę tekstur glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_1D); 2D przebija 1D. Tekstury
Modulacja i mieszanie kolorów: glTexEnv Chcemy uwzględnić dotychczasowy kolor obiektu na który nakładana jest tekstura, np. w celu uzyskania efektu oświetlonej tekstury. Używamy do tego funkcji glTexEnv w jednej z następujących form: voidglTexEnvf(GLenumtarget, GLenumpname, TYPE param);voidglTexEnvi(GLenumtarget, GLenumpname, TYPE param); voidglTexEnvfv(GLenumtarget,GLenumpname,TYPE *param);voidglTexEnviv(GLenumtarget,GLenumpname,TYPE *param); W podstawowej wersji parametry target i pnameprzyjmują wartości: target: GL_TEXTURE_ENV pname: GL_TEXTURE_ENV_MODE | GL_TEXTURE_ENV_COLOR . Tekstury
Modulacja i mieszanie kolorów: glTexEnv Wywołanie z parametrem GL_TEXTURE_ENV_COLORma charakter pomocniczy. *paramwskazuje wówczas na czteroelementową tablicę RGBA i wykorzystuje jej zawartość (barwę) w kolejnym wywołaniu z parametrem GL_TEXTURE_ENV_MODE Tekstury
Modulacja i mieszanie kolorów: glTexEnv, c.d. Wywołanie z pname = GL_TEXTURE_ENV_MODE, wymaga podania jako param wartości: GL_DECAL, GL_REPLACE, GL_MODULATE, GL_BLEND. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); Tekstury