Oprogramowanie i wykorzystanie stacji roboczych Wykład 8 O
Transkrypt
Oprogramowanie i wykorzystanie stacji roboczych Wykład 8 O
Oświetlenie w OpenGL W OpenGL źródło światła w scenie składa sie˛ z trzech składowych oświetlenia: otoczenia, rozpraszania, odbłysków. Oprogramowanie i wykorzystanie stacji roboczych Ż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 sie˛ ono raczej z różnych intensywności każdego z jego rodzajów. Wykład 8 Dr inż. Tomasz Olas [email protected] Instytut Informatyki Teoretycznej i Stosowanej Politechnika Cz˛estochowska Wykład 8 – p. 1/23 Światło otaczajace ˛ Wykład 8 – p Światło rozproszone to światło, które nie pochodzi z żadnego określonego kierunku. Ma swoje źródło, jednak promienie światła odbijaja˛ sie˛ 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. 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 wiekszym ˛ katem ˛ (oświetlenie jarzeniowe, światło słoneczne padajace ˛ w boczne okno w południe). Światło otaczajace ˛ ambient Światło rozproszone diffuse Wykład 8 – p. 3/23 Wykład 8 – p Oświetlenie w OpenGL - przykład Światło odbłysków Podobnie jak światło rozproszone, światło odbłysków specular posiada kierunek, ale jest odbijane ostro i w jedna˛ strone. ˛ 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 Wykład 8 – p. 5/23 Przygotowanie oświetlenia Wykład 8 – p Przygotowanie oświetlenia - przykład // Określenie jasnego białego światła GLfloat ambientLight[] = {1.0f, 1.0f, 1.0f, 1,0f}; Aby poinformować OpenGL, że ma zaczać ˛ obliczać oświetlenie należy wywołać: glEnable(GL_LIGHTING); 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: Wykład 8 – p. 7/23 // Ustawienie modelu oświetlenia, tak aby korzystał // ze światła otoczenia określonego w ambientLight glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); Wykład 8 – p Dodawanie źródeł światła - przykład Dodanie źródeł światła Do ustawienia parametrów źródła światła służy funkcja glLight: void MyGLWidget::initializeGL() { ... glLight[fi]v(GLenum light, GLenum pname, GLfloat* params); gdzie: 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}; 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 sie˛ we wskazanym miejscu. W przeciwnym razie źródło światła jest kierunkowe i promienie sa˛ równoległe. glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); glEnable(GL_LIGHT0); ... } params - Tablica liczb zmiennopozycyjnych lub całkowitych zawierajacych ˛ wartości ustawianych parametrów. Wykład 8 – p. 9/23 Źródła światła - światło otaczajace ˛ Wykład 8 – p. Źródła światła - światło rozproszone GLfloat ambientLight[] = {0.5f, 0.5f, 0.5f, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); GLfloat GLfloat GLfloat GLfloat ... 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); diffuseLight0[] = {0.8f, 0.8f, 0.8f, 1.0f}; specularLight0[] = { 0.0f, 0.0f, 0.0f, 1.0f}; ambientLight0[] = {0.3f, 0.3f, 0.3f, 1.0f}; 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}; Wykład 8 – p. 11/23 Wykład 8 – p. Źródła światła - pozycja I Źródła światła - pozycja II GLfloat positionLight0[] = {2.0f, 2.0f, 2.0f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, positionLight0); GLfloat positionLight0[] = {0.0f, 0.0f, 1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, positionLight0); GLfloat positionLight0[] = {-4.0f, -4.0f, 2.0f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, positionLight0); GLfloat positionLight0[] = {0.0f, 1.0f, 1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, positionLight0); GLfloat positionLight0[] = {1.0f, 1.0f, -1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, positionLight0); Wykład 8 – p. 13/23 Wykład 8 – p. Właściwości materiału (II) Właściwości materiału glMaterial[fi](GLenum face, GLenum pname, TYPE param); glMaterial[fi]v(GLenum face, GLenum pname, const TYPE* params); Światło jest tylko jednym z elementów wystepuj ˛ acych ˛ w modelowaniu oświetlenia. gdzie: Obiekty nie tylko posiadaja˛ swój kolor, ale moga˛ w różny sposób odbijać poszczególne składowe światła. face - Określa strone˛ wielokata, ˛ do której bedzie ˛ sie˛ odnosić dane wywołanie funkcji (GL_FRONT - przednia strona, GL_BACK - tylna strona, GL_FRONT_AND_BACK - obie strony). Obiekty moga˛ również emitować własne światło. Parametr pname okresla zmieniana wartosc parametru materiału: GL_AMBIENT - składowe RGBA okreslajace stopien odbicia swiatła otaczajacego, Do określenia właściwości materiału służy funkcja glMaterialfv: GL_DIFFUSE - składowe RGBA okreslajace stopien rozproszenia swiatła rozproszonego, GLFloat gray[] = {0.75f. 0.75f, 0.75f, 1.0f); ... glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray); 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, 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(); 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. Wykład 8 – p. 15/23 Wykład 8 – p. Normalne do powierzchni Śledzenie kolorów 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 sie˛ poprzez wywołanie funkcji: Normalna˛ do powierzchni określa sie˛ poprzez: glNormal3[bisdf](TYPE nx, TYPE ny, TYPE nz); glNormal3[bisdf]v(const TYPE* v); glEnable(GL_COLOR_MATERIAL); Nastepnie ˛ funkcja˛ glColorMaterial określa sie˛ właściwości materiału, które bed ˛ a˛ ustawiane zgodnie z wartościami przekazanymi funkcji glColor. Przykład: glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); Wykład 8 – p. 17/23 Wykład 8 – p. Normalne jednostkowe Określenie normalnej dla trójkata ˛ 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: void calcNormal(GLfloat p0[3], GLfloat p0[3], GLfloat p0[3], GLfloat normal[3]) { GLfloat v1[3]; GLfloat v2[3]; glEnable(GL_NORMALIZE); // obliczenie v1[0] = p0[0] v1[1] = p0[1] v1[2] = p0[2] - dwóch wektorów na podstawie trzech punktów p1[0]; p1[1]; p1[2]; W wiekszoś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; v2[0] = p1[0] - p2[0]; v2[1] = p1[1] - p2[1]; v2[2] = p1[2] - p2[2]; v[0] /= length; v[1] /= length; v[2] /= length; // 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]; } } Wykład 8 – p. 19/23 Wykład 8 – p. Normalne do powierzchni - przykład 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(); Uśrednianie normalnych - przykład (I) 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]; } } Wykład 8 – p. 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(); Wykład 8 – p. 23/23 Wykład 8 – p.