Programowanie grafiki 3D Podstawy OpenGL cz.1 Kolory i cieniowanie Krawędzie i powierzchnie prymitywów Bufor głębokości Oświetlenie Wektory normalne
Kolory i cieniowanie void glColor3b(GLbyte R, GLbyte G, GLbyte B) void glColor3d(GLdouble R, GLdouble G, GLdouble B) void glColor3f(GLfloat R, GLfloat G, GLfloat B) void glColor3i(GLint R, GLint G, GLint B) void glColor3s(GLshort R, GLshort G, GLshort B) void glColor3ub(GLubyte R, GLubyte G, GLubyte B) void glColor3ui(GLuint R, GLuint G, GLuint B) void glColor3us(GLushort R, GLushort G, GLushort B) void glColor3bv(const GLbyte *v) void glColor3dv(const GLdouble *v) void glColor3fv(const GLfloat *v) void glColor3iv(const GLint *v) void glColor3sv(const GLshort *v) void glColor3ubv(const GLubyte *v) void glColor3uiv(const GLuint *v) void glColor3usv(const GLushort *v)
Kolory i cieniowanie void glColor4b(GLbyte R, GLbyte G, GLbyte B, GLbyte A) void glColor4d(GLdouble R, GLdouble G, GLdouble B, GLdouble A) void glColor4f(GLfloat R, GLfloat G, GLfloat B, GLfloat A) void glColor4i(GLint R, GLint G, GLint B, GLint A) void glColor4s(GLshort R, GLshort G, GLshort B, GLshort A) void glColor4ub(GLubyte R, GLubyte G, GLubyte B, GLubyte A) void glColor4ui(GLuint R, GLuint G, GLuint B,GLuint A) void glColor4us(GLushort R, GLushort G, GLushort B,GLushort A) void glColor4bv(constGLbyte *v) void glColor4dv(constGLdouble *v) void glColor4fv(constGLfloat *v) void glColor4iv(constGLint *v) void glColor4sv(constGLshort *v) void glColor4ubv(constGLubyte *v) void glColor4uiv(constGLuint *v) void glColor4usv(constGLushort *v)
Kolory i cieniowanie Wszystkie składowe kolorów muszą się zmieniać w zakresie <-1;1>. typ OpenGL konwersja GLubyte (0 : 255) GLbyte (-128: 127) GLushort (0 : 65 535) GLshort (-32 768 : 32 767) GLuint (0 : 4 294 967 295) GLint (-2147 483 648 : 2 147 483 647)
Kolory i cieniowanie Wyboru sposobu cieniowania dokonujemy funkcją: void glShadeModel(GLenum mode) z jednym z parametrów: GL_FLAT lub GL_SMOOTH (algorytm Gourauda). Dla każdego kanału niezależnie można włączyć lub wyłączyć zapis do bufora kolorów: void glColorMask(GLboolean R, GLboolean G, GLboolean B, GLboolean A)
Krawędzie i powierzchnie prymitywów Każdy wielokąt (ściana) w OpenGL ma dwie strony przednią i tylną. Domyślnie przednią ścianą jest ta, której wierzchołki uporządkowane są przeciwnie do ruchu wskazówek zegara. Można to zmienić funkcją: void glFrontFace(GLenum mode); wstawiając jako parametr: GL_CW (zgodnie z ruchem wskazówek zegara) lub GL_CCW (przeciwnie). Standardowo rysowane są obie strony każdej ze ścian. Opcją: void glEnable(GL_CULL_FACE); możemy włączyć wybór stron ściany do nie rysowania. Wyboru nie rysowanej strony wielokąta dokonujemy funkcją: void glCullFace(GLenum mode); GL_FRONT – nie będzie rysowana przednia ściana, GL_BACK – nie będzie rysowana tylna ściana, GL_FRONT_AND_BACK – nie będzie rysowana żadna ze ścian.
Krawędzie i powierzchnie prymitywów Wybór sposobu rysowania różnych stron wielokątów: void glPolygonMode(GLenum face, GLenum mode); face: GL_FRONT, GL_BACK, GL_FRONT_AND_BACK, mode: GL_POINT, GL_LINE, GL_FILL. Wypełnianie ścian wzorem włączamy: void glEnable(GL_POLYGON_STIPPLE); Wzorzec wypełnienia ustawiamy funkcją: void glPolygonStipple(const GLubyte *mask); Aktualne wypełnienie pobieramy funkcją: void glGetPolygonStipple(GLubyte *mask); Wskaźnik *mask wskazuje na mapę bitową o rozmiarach 32x32 zapisaną w postaci 128 wartości typu GLubyte. Wartości w tablicy zapisywane są od dolnego wiersza do górnego.
Krawędzie i powierzchnie prymitywów Rysowanie pojedynczych krawędzi wielokąta można włączać i wyłączać funkcjami: void glEdgeFlag(GLboolean flag); void glEdgeFlagv(GLboolean *flag); Po podaniu do funkcji wartości argumentu GL_TRUE, krawędzie będą rysowane aż do momentu wywołania funkcji z wartością parametru równą GL_FALSE. I odwrotnie.
Bufor głębokości Zasada działania bufora głębokości (z–bufora).
Bufor głębokości Standardowo bufor ramki nie używa bufora głębokości. Aby program mógł korzystać z z-bufora na etapie inicjalizacji OpenGL należy użyć stałej GLUT_DEPTH. void glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGB| GLUT_DEPTH); Dołączenie bufora głębokości do bufora ramki nie powoduje automatycznie jego użycia. Testowanie głębokości włączamy ustawiając odpowiednią zmienną stanu: glEnable(GL_DEPTH_TEST); Chwilowe włączanie i wyłączanie zapisywania danych do bufora głębokości realizuje funkcja: glDepthMask (Glboolean flag); gdzie flag może przyjmować wartości GL_FALSE i GL_TRUE. UWAGA: testy głębokości są nadal wykonywane, tylko wartości w buforze nie są zmieniane. Przed rozpoczęciem rysowania z-bufor należy wyczyścić: glClear(GL_DEPTH_BUFFER_BIT); Bufor czyszczony jest wartością 1. Można to zmienić wywołując funkcję: void glClearDepth(Glclamped depth); Której argumentem musi być liczba z przedziału <0;1>.
Bufor głębokości Zakres zmienności wartości w buforze głębokości można zmienić funkcją: void glDepthRange (Glclampd zNear, Glclampd zFar); Oba argumenty muszą być z przedziału <0;1>. Należy jednak pamiętać, że zawężenie zakresu bufora głębokości zmniejsza precyzję jego działania. W wyjątkowych sytuacjach, gdy zmieniamy model współrzędnych i orientację osi Z (lub wykonujemy inne eksperymenty) trzeba zmienić rodzaj testu wykonywanego na buforze głębokości: glDepthFunc(Glenum func); gdzie func może przyjmować wartości: GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS.
Oświetlenie Światło otaczające • nie pochodzi z żadnego konkretnego kierunku • równomiernie oświetla wszystkie elementy sceny Światło rozproszone •wyróżniony kierunek padania •na obiektach rozprasza się równomiernie we wszystkich kierunkach Światło kierunkowe •wyróżniony kierunek padania •zachowuje prawo padania i odbicia od obiektów
Oświetlenie Włączenie obliczeń związanych z oświetleniem: glEnable(GL_LIGHTING); Identyfikatory źródeł światła mają postać: GL_LIGHT0, … , GL_LIGHTn gdzie n na końcu ostatniego identyfikatora oznacza liczbę dostępnych źródeł światła (GL_MAX_LIGHTS) pomniejszoną o 1. Specyfikacja przewiduje co najmniej 8 źródeł. Można używać odwołań postaci: GL_LIGHTi=GL_LIGHT0+i Światło kierunkowe Światło punktowe Światło punktowe typu reflektor
Oświetlenie Jednoargumentowe parametry źródeł światła ustawiamy funkcjami: void glLightf(GLenum light, GLenum pname, GLfloat param); void glLighti(GLenum light, GLenum pname, GLint param); pname znaczenie GL_SPOT_EXPONENT Wykładnik tłumienia kątowego z zakresu <0;128>. Opisuje „ściemnianie” światła od centrum na zewnątrz reflektora (funkcja cosinus). GL_SPOT_CUTOFF Kąt odcięcia reflektora z zakresu <0;90>. Dla wartości 180 światło rozchodzi się równomiernie w całej przestrzeni. GL_CONSTANT_ATTENUATION Wielkość tłumienia w funkcji odległości d wierzchołka od źródła światła: GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATON
Oświetlenie Wieloargumentowe* parametry źródeł światła ustawiamy funkcjami: void glLightfv(GLenum light, GLenum pname, const GLfloat *params); void glLightiv(GLenum light, GLenum pname, const GLint *params); pname znaczenie GL_AMBIENT Wartości RGBA światła otaczającego. GL_DIFFUSE Wartości RGBA światła rozproszonego. GL_SPECULAR Wartości RGBA światła odbitego. GL_POSITION Tablica (x,y,z,w). Jeśli w=1 to (x,y,z) określają położenie źródła. Jeśli w=0 to (x,y,z) określają kierunek światła źródła kierunkowego. Wektor skierowany jest ku źródłu. GL_SPOT_DIRECTION Kierunek padania światła kierunkowego. *Funkcji tych można używać również do parametrów jednoargumentowych, choć lepiej użyć tych z poprzedniego slajdu.
Właściwość źródła światła Oświetlenie Właściwość źródła światła Wartości domyślne GL_LIGHT0 Pozostałe źródła GL_AMBIENT (0,0,0,1) GL_DIFFUSE (1,1,1,1) GL_SPECULAR GL_POSITION (0,0,1,0) GL_SPOT_DIRECTION (0,0,-1) GL_SPOT_EXPONENT GL_SPOT_CUTOFF 180 GL_CONSTANT_ATTENUATION 1 GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
Oświetlenie Odczyt własności poszczególnych źródeł światła umożliwiają funkcje: void glGetLightfv(GLenum light, GLenum pname, GLfloat *params) void glGetLightiv(GLenum light, GLenum pname, GLint *params) UWAGA. Wartości oświetlenia wyliczane są tylko w wierzchołkach rysowanej bryły. Po wyliczeniu oświetlenia w wierzchołkach, OpenGL interpoluje stan oświetlenia w pozostałych punktach.
Oświetlenie Właściwości modelu oświetlenia ustala się wywołując funkcje: void glLightModelf (GLenum pname, GLfloat param) void glLightModeli (GLenum pname, GLint param) void glLightModelfv (GLenum pname, const GLfloat *params) void glLightModeliv (GLenum pname, const GLint *params) pname wartość domyślna GL_LIGHT_MODEL_LOCAL_VIEWER GL_FALSE GL_LIGHT_MODEL_TWO_SIDE GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_SINGLE_COLOR
Oświetlenie GL_LIGHT_MODEL_LOCAL_VIEWER określa sposób liczenia kąta przy odbiciu. Dokładnie w kierunku kamery (GL_TRUE) lub w sposób uproszczony, ale szybszy, w kierunku osi z (GL_FALSE). GL_LIGHT_MODEL_TWO_SIDE określa strony wielokątów, które będą brane pod uwagę przy wyliczaniu oświetlenia: przednia i tylna (GL_TRUE) lub tylko przednia (GL_FALSE). GL_LIGHT_MODEL_AMBIENT ustala parametry światła otoczenia, które jest obecne nawet pod nieobecność innych źródeł światła. Początkowo ustawione jest dość ciemne światło: (0.2,0.2,0.2,1) GL_LIGHT_MODEL_COLOR_CONTROL parametr istotny dopiero przy nakładaniu tekstur. Kontroluje sposób mieszania oświetlenia z teksturą (czy najpierw tekstura później oświetlenie, czy oba na raz).
Wektory normalne Z każdym wierzchołkiem w OpenGL związany jest wektor normalny. Wektor ten wykorzystywany jest przy obliczeniach związanych z oświetleniem. Wskazuje on także zewnętrzną stronę danego prymitywu. W najprostszym przypadku wektor normalny w każdym wierzchołku prymitywu jest taki sam. Prymityw taki będzie się wydawał płaski. Technika uśredniania wektorów normalnych pozwala symulować gładkie (krągłe) przejścia pomiędzy prymitywami.
Wektory normalne Wektory normalne tworzone są równocześnie z definiowanymi wierzchołkami. Chcąc wierzchołkom nadać własne wektory normalne korzystamy z funkcji: void glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz) void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) void glNormal3i (GLint nx, GLint ny, GLint nz) void glNormal3s (GLshort nx, GLshort ny, GLshort nz) bądź w wersjach tablicowych: void glNormal3bv(const GLbyte *v) void glNormal3dv(const GLdouble *v) void glNormal3fv(const GLfloat *v) void glNormal3iv(const GLint *v) void glNormal3sv(const GLshort *v)
Wektory normalne W pewnych sytuacjach łatwo wyznaczyć kierunek wektorów normalnych. Wektory normalne powinny być zawsze znormalizowane. Można o to dbać samodzielnie lub też włączyć automatyczną normalizację wektorów normalnych: glEnable(GL_NORMALIZE);
test