Oświetlenie w OpenGL Oprogramowanie i wykorzystanie stacji roboczych Wykład 8 Dr inż. Tomasz Olas olas@icis.pcz.pl W OpenGL źródło światła w scenie składa się z trzech składowych oświetlenia: otoczenia, rozpraszania, odbłysków. Żadne źródło światła nie jest złożone wyłacznie z jednego, z wyżej wymienionych rodzajów światła. Składa się ono raczej z różnych intensywności każdego z jego rodzajów. Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska. 1/23 Światło otaczajace Światło rozproszone Światło otaczajace ambient to światło, które nie pochodzi z żadnego określonego kierunku. Ma swoje źródło, jednak promienie światła odbijaja się po całym pomieszczeniu lub scenie i generalnie sa pozbawione kierunku. Obiekty iluminowane światłem otaczajacym sa równomiernie oświetlone na wszystkich powierzchniach we wszystkich kierunkach. Światło rozproszone diffuse pochodzi z konkretnego kierunku, lecz jest odbijane od powierzchni równomiernie, powierzchnia jest jaśniejsza, gdy światło pada na nia bezpośrednio, niż wtedy, gdy pada na nia pod większym katem (oświetlenie jarzeniowe, światło słoneczne padajace w boczne okno w południe).. 3/23
Światło odbłysków Oświetlenie w OpenGL - przykład Podobnie jak światło rozproszone, światło odbłysków specular posiada kierunek, ale jest odbijane ostro i w jedna stronę. Bardziej pobłyskujace obiekty możemy poznać po jasnych, lśniacych plamach światła na ich powierzchniach. Podobnie jak kolory każda składowa światła jest definiowany przez wartość RGBA. Przykład - czerwone światło lasera Czerwony Zielony Niebieski Alfa Odbłysków 0.99 0.0 0.0 1.0 Rozproszone 0.10 0.0 0.0 1.0 Otaczajace 0.05 0.0 0.0 1.0 Przygotowanie oświetlenia. 5/23 Przygotowanie oświetlenia - przykład Aby poinformować OpenGL, że ma zaczać obliczać oświetlenie należy wywołać: glenable(gl_lighting); Domyślne wartości RGBA globalnego światła otaczajacego to (0.2, 0.2, 0.2, 1.0). Można to zmienić poprzez wywołanie funkcji gllightmodel z pierwszym parametrem ustawionym na GL_LIGHT_MODEL_AMBIENT: // Określenie jasnego białego światła GLfloat ambientlight[] = 1.0f, 1.0f, 1.0f, 1,0f; glenable(gl_lighting); // Ustawienie modelu oświetlenia, tak aby korzystał // ze światła otoczenia określonego w ambientlight gllightmodelfv(gl_light_model_ambient, ambientlight);. 7/23
Dodanie źródeł światła Do ustawienia parametrów źródła światła służy funkcja gllight: gllight[fi]v(glenum light, GLenum pname, GLfloat* params); gdzie: light - Określa źródło światła, którego parametry chcemy zmodyfikować: GL_LIGHT0, GL_LIGHT1, pname Określa właściwość światła, która chcemy zmodyfikować: GL_AMBIENT - Określa składowa światła otoczenia (cztery składowe RGBA), GL_DIFFUSE - Określa składowa światła rozproszonego (cztery składowe RGBA), GL_SPECULAR - Określa składowa światła odbłysków (cztery składowe RGBA), GL_POSITION - pierwsze trzy elementy określaja położenie źródła światła. Jeśli czwarty element ma wartość 1.0, światło rzeczywiście znajduje się we wskazanym miejscu. W przeciwnym razie źródło światła jest kierunkowe i promienie sa równoległe. params - Tablica liczb zmiennopozycyjnych lub całkowitych zawierajacych wartości ustawianych parametrów. Dodawanie źródeł światła - przykład void MyGLWidget::initializeGL() GLfloat ambientlight[] = 0.3f, 0.3f, 0.3f, 1.0f; GLfloat diffuselight[] = 0.7f, 0.7f, 0.7f, 1.0f; GLfloat lightposition[] = 2.0f, 2.0f, 2.0f, 0.0f; gllightfv(gl_light0, GL_AMBIENT, ambientlight); gllightfv(gl_light0, GL_DIFFUSE, diffuselight); gllightfv(gl_light0, GL_POSITION, lightposition); glenable(gl_light0); Źródła światła - światło otaczajace GLfloat ambientlight[] = 0.5f, 0.5f, 0.5f, 1.0f; gllightmodelfv(gl_light_model_ambient, ambientlight); GLfloat ambientlight0[] = 0.5f, 0.5f, 0.5f, 1.0f; GLfloat diffuselight0[] = 0.0f, 0.0f, 0.0f, 1.0f; GLfloat specularlight0[] = 0.0f, 0.0f, 0.0f, 1.0f; gllightfv(gl_light0, GL_AMBIENT, ambientlight0); gllightfv(gl_light0, GL_DIFFUSE, diffuselight0); gllightfv(gl_light0, GL_SPECULAR, specularlight0); glenable(gl_light0);. 9/23 Źródła światła - światło rozproszone GLfloat diffuselight0[] = 0.8f, 0.8f, 0.8f, 1.0f; GLfloat specularlight0[] = 0.0f, 0.0f, 0.0f, 1.0f; GLfloat ambientlight0[] = 0.3f, 0.3f, 0.3f, 1.0f; GLfloat positionlight0[] = 2.0f, 2.0f, 2.0f, 1.0f; GLfloat diffuselight0[] = 0.5f, 0.5f, 0.5f, 1.0f;. GLfloat diffuselight0[] = 0.9f, 0.0f, 0.0f, 1.0f;. 11/23.
Źródła światła - pozycja I Źródła światła - pozycja II GLfloat positionlight0[] = 2.0f, 2.0f, 2.0f, 1.0f; GLfloat positionlight0[] = 0.0f, 0.0f, 1.0f, 0.0f; GLfloat positionlight0[] = -4.0f, -4.0f, 2.0f, 1.0f; GLfloat positionlight0[] = 0.0f, 1.0f, 1.0f, 0.0f; GLfloat positionlight0[] = 1.0f, 1.0f, -1.0f, 0.0f;. 13/23. Właściwości materiału Światło jest tylko jednym z elementów występujacych w modelowaniu oświetlenia. Obiekty nie tylko posiadaja swój kolor, ale moga w różny sposób odbijać poszczególne składowe światła. Obiekty moga również emitować własne światło. Do określenia właściwości materiału służy funkcja glmaterialfv: GLFloat gray[] = 0.75f. 0.75f, 0.75f, 1.0f); glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, gray); glbegin(gl_triangles); glvertex3f(1.0f, 1.0f, 0.0f); glvertex3f(1.0f, -1.0f, 0.0f); glvertex3f(-1.0f, 0.0f, 0.0f); glend(); Właściwości materiału (II) glmaterial[fi](glenum face, GLenum pname, TYPE param); glmaterial[fi]v(glenum face, GLenum pname, const TYPE* params); gdzie: face - Określa stronę wielokata, do której będzie się odnosić dane wywołanie funkcji (GL_FRONT - przednia strona, GL_BACK - tylna strona, GL_FRONT_AND_BACK - obie strony). Parametr pname okresla zmieniana wartosc parametru materiału: GL_AMBIENT - składowe RGBA okreslajace stopien odbicia swiatła otaczajacego, GL_DIFFUSE - składowe RGBA okreslajace stopien rozproszenia swiatła rozproszonego, GL_AMBIENT_AND_DIFFUSE - składowe RGBA okreslajace jednoczesnie stopien odbicia swiatła otaczajacego i stopien rozproszenia swiatła rozproszonego, GL_SPECULAR - składowe RGBA okreslajace stopien odbicia swiatła odbitego, GL SHININESS - stała z przedziału [0, 128] okreslajaca wykładnik odbłysku swiatła czyli regulacje stopnia wystepowania efektu rozbłysku obiektu; im wieksza wartosc, tym wieksze skupienie rozbłysku swiatła na obiekcie, GL_EMISSION - składowe RGBA swiatła emitowanego przez obiekt; taki obiekt nie staje sie zródłem swiatła i nie oswietla innych obiektów sceny, wymaga to takze utworzenia zródła swiatła.. 15/23.
Śledzenie kolorów Normalne do powierzchni Druga metoda ustalania własności materiałów jest metoda zwana śledzeniem kolorów. W tym przypadku ustawianie właściwości materiału jest dokonywane w momencie wywołania funkcji glcolor. Właczenie metody śledzenia kolorów dokonuje się poprzez wywołanie funkcji: glenable(gl_color_material); Następnie funkcja glcolormaterial określa się właściwości materiału, które będa ustawiane zgodnie z wartościami przekazanymi funkcji glcolor. Przykład: glenable(gl_color_material); glcolormaterial(gl_front, GL_AMBIENT_AND_DIFFUSE); Normalna do powierzchni określa się poprzez: glnormal3[bisdf](type nx, TYPE ny, TYPE nz); glnormal3[bisdf]v(const TYPE* v); Określenie normalnej dla trójkata. 17/23 Normalne jednostkowe. void calcnormal(glfloat p0[3], GLfloat p0[3], GLfloat p0[3], GLfloat normal[3]) GLfloat v1[3]; GLfloat v2[3]; // obliczenie dwóch wektorów na podstawie trzech punktów v1[0] = p0[0] - p1[0]; v1[1] = p0[1] - p1[1]; v1[2] = p0[2] - p1[2]; v2[0] = p1[0] - p2[0]; v2[1] = p1[1] - p2[1]; v2[2] = p1[2] - p2[2]; // obliczenie iloczynu wektorowego dwoch wektorow normal[0] = v1[1] * v2[2] - v1[2] * v2[1]; normal[1] = v1[2] * v2[0] - v1[0] * v2[2]; normal[2] = v1[0] * v2[1] - v1[1] * v2[0]; W OpenGL wszystkie normalne do powierzchni musza zostać zamienione na normalne jednostkowe (wektor o długości 1). Istnieja dwa sposoby realizacji tego wymogu: Automatyczne zamienianie wektorów normalnych na normalne jednostkowe: glenable(gl_normalize); W większości wypadków wydajniejszym rozwiazaniem jest wcześniejsze wykonanie normalizacji: void ReduceToUnit(GLfloat v[3]) double length = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) if (length < ZERO) length = 1.0; v[0] /= length; v[1] /= length; v[2] /= length;. 19/23.
Normalne do powierzchni - przykład Uśrednianie normalnych - przykład (I) glbegin(gl_triangles); for (int i = 0; i < 12; i++) calcnormal(nodes[triangles[i][0]], nodes[triangles[i][1]], nodes[triangles[i][2]], n); glnormal3fv(n); glvertex3fv(nodes[triangles[i][0]]); glvertex3fv(nodes[triangles[i][1]]); glvertex3fv(nodes[triangles[i][2]]); glend(); glenable(gl_smooth); GLfloat normals[8][3]; GLfloat n[3]; for (int i = 0; i < 12; i++) calcnormal(nodes[triangles[i][0]], nodes[triangles[i][1]], nodes[triangles[i][2]], n); for (int j = 0; j < 3; j++) normals[triangles[i][j]][0] += n[0]; normals[triangles[i][j]][1] += n[1]; normals[triangles[i][j]][2] += n[2];. 21/23. Uśrednianie normalnych - przykład (II) glbegin(gl_triangles); for (int i = 0; i < 12; i++) glnormal3fv(normals[triangles[i][0]]); glvertex3fv(nodes[triangles[i][0]]); glnormal3fv(normals[triangles[i][1]]); glvertex3fv(nodes[triangles[i][1]]); glnormal3fv(normals[triangles[i][2]]); glvertex3fv(nodes[triangles[i][2]]); glend();. 23/23