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.