WOJSKOWA AKADEMIA TECHNICZNA
Grafika komputerowa
Sprawozdanie z pracy laboratoryjnej nr 4
Temat: Modelowanie oświetlenia
Wykonujący ćwiczenie: Barbara Szwal
Prowadzący: dr inż. Marek Salomon
Data wykonania ćwiczenia: 03.01.2013
Grupa szkoleniowa: I1Y5S1
1.Treść zadania.
Wykorzystując biblioteki OpenGL i GLUT napisać program przedstawiający perspektywiczny obraz obiektu o następujących parametrach:
Typ obiektu: bryła z ćwicz. 2 o zmiennej parzystej liczbie podziałów pionowych i poziomych,
Właściwości materiału nr 1: zielony matowy (widziany w białym świetle),
Właściwości materiału nr 2: fioletowy błyszczący (widziany w białym świetle),
Sposób przyporządkowania materiałów do obiektu zgodnie ze wzorem: szachownica z uwzględnieniem podziałów poziomych i pionowych.
Obiekt należy oświetlić dwoma źródłami światła o następujących parametrach:
Źródło nr 1:
typ: reflektor (ang. spot),
kolor: żółty,
natężenie: 1,
kąt odcięcia: 45o,
położenie: zmienne po orbicie kołowej o środku w punkcie S(0,0,0) z możliwością interaktywnej zmiany następujących parametrów:
promienia orbity,
prędkości kątowej (3 różne prędkości),
kąta nachylenia orbity do osi OX,
kierunek świecenia: na obiekt.
Źródło nr 2:
typ: kierunkowe,
kolor: czerwony,
natężenie: 0.8,
położenie: stałe w punkcie P(-10,1 0, 10) układu współrzędnych sceny.
kierunek świecenia: na obiekt.
c) interaktywną zmianę wielkości bryły;
odległości obserwatora od środka układu współrzędnych sceny;
kąta obrotu wokół osi OY w zakresie [0o, 360o] z krokiem 1o.
Oświetlony obiekt powinien zawsze znajdować się w centralnej części okna
2.Sposób rozwiązania.
Aby przystąpić do wykonania zadania należy znać dobrze funkcje pochodzące z bibliotek OpenGL i GLUT, które umożliwiają nam rysowanie obiektów za pomocą prymitywów oraz przekształcenia przestrzeni (obroty, przesunięcia, operacje na macierzach). Wszystkie te rzeczy były wykonywane na 2 i 3 laboratoriach.
Do pokrycia zbudowanej przez nas bryły materiałem musimy określić parametry materiału:
1.GL_AMBIENT - współczynnik odbicia światła otoczenia
2.GL_DIFFUSE -współczynnik odbicia światła rozproszonego
3.GL_SPECULAR - współczynnik odbicia światła lustrzanego
4.GL_SHININESS – połysk
5.GL_EMISSION – kolor światła emitowanego
Do definiowania właściwości materiału użyliśmy następujących funkcji void glMaterial{if}[v](GLenum face, GLenum pname, TYPE param) – funkcja służąca do określenia właściwości materiału w celu modelowania oświetlenia. Parametr face określa, do której strony obiektu odnoszą się definiowane ustawienia. Może przyjmować wartości: GL_FRONT, GL_BACK, GL_FRONT_AND_BACK. Parametr pname określa modyfikowany parametr, a param wartość, która ma zostać mu przypisana.
Do definicji wektorów normalnych wykorzystaliśmy funkcję:
-void glNormal3{bsidf}(TYPE nx, ny, nz);
-void glNormal3{bsidf}v(cont TYPE *v);
Funkcja ustala aktualny wektor normalny. Argumentami mogą być trzy współrzędne wektora [nx, ny, nz] lub wskaźnik do tablicy te współrzędne zawierające(v).
Każdy z tych parametrów przedstawiamy w postaci wektora wartości, który przedstawia wartości RGBA, gdzie R – red, G – green, B – blue, A – współczynnik określający natężenie barwy (im mniejszy współczynnik, tym bardziej przezroczysty materiał, gdy jest równy 0, to materiał przyjmuje barwę otoczenia). Każdy ze współczynników oprócz połysku przyjmuje wartości od [0.0-1.0]. Połysk przyjmuje wartości [0.0-128.0].
Inicjowanie materiału dokonuje się, np. za pomocą funkcji:
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
Gdzie 1 parametr określa, że materiałem ma być pokryta widoczna część bryły, 2 parametr mówi o tym, który rodzaj współczynnika będziemy określać i ostatni parametr jest wektorem określającym współczynniki RGBA.
Materiał błyszczący: aby go uzyskać musimy podać większe wartości GL_SPECULAR, a mniejsze GL_DIFFUSE. Dzięki temu uzyskamy efekt dużego odbicia światła i małego pochłaniania, czyli materiał będzie wydawał się błyszczący.
Materiał matowy: do uzyskania tego efektu podajemy większe wartości GL_DIFFUSE, a mniejsze GL_SPECULAR. Dzięki temu materiał będzie dużą cześć światła pochłaniał, odbijając małą jego część i materiał będzie się wydawał matowy.
Materiał emitujący: aby uzyskać taki efekt musimy ustawić w odpowiedni sposób parametr GL_EMISSION, tak aby kolor światła emitowanego był odpowiedni. (W poprzednich przypadkach parametr ten mógł nie być używany).
Po określeniu materiałów należało określić w odpowiedni sposób światła, które będą oświetlały nasz obiekt. Robimy to w podobny sposób jak w przypadku materiałów:
1.GL_AMBIENT - światło otoczenia (brak określonego kierunku),
2.GL_DIFFUSE – światło rozproszone (główny składnik światła),
3.GL_SPECULAR – światło zwierciadlane,
4.GL_POSITION – określa pozycje światła (4 składowa 1.0 dla reflektora, 0.0 dla światła kierunkowego),
5.GL_SPOT_DIRECTION – kierunek świecenia reflektora,
6.GL_SPOT_CUTOFF – połowa kąta rozwarcia światła reflektora.
Światło jest inicjowane za pomocą funkcji:
glLightfv(GL_LIGHT2, GL_DIFFUSE, swiatlo2[1]);
Gdzie 1 parametr mówi o tym, które światło będziemy określać, 2 – który rodzaj współczynnika będziemy określać i ostatni wskazuje na wektor wartości RGBA.
Zadanie 1
Projektowanie modelu i oświetlenia rozpoczęłam od zdefiniowania właściwości materiałów i świateł:
//Macierze definiujace materialy
//zielony matowy
const GLfloat ambient_m1[4] = {0,1,0,1};
const GLfloat diffuse_m1[4] = {0,1,0,1};
GLfloat specular_m1[4] = {0,0.1,0,0.1};
// filetowy polysk
const GLfloat ambient_m2[4] = {0.8,0,0.8,1};
const GLfloat diffuse_m2[4] = {0.5,0,0.5,1};
GLfloat specular_m2[4] = {1,0,1,1};
//Macierze definiujace swiatla
//reflektor
GLfloat ambient_s1[4] = {1,1,0,1};
GLfloat diffuse_s1[4] = {1,1,0,1};
GLfloat specular_s1[4] = {1,1,0,1};
GLfloat position_s1[] = {0,0,0,1};
GLfloat direction_s1[] = {0,-1,0};
// kierunkowe
GLfloat ambient_s2[4] = {0.8,0,0,1};
GLfloat diffuse_s2[4] = {0.8,0,0,1};
GLfloat specular_s2[4] = {0.8,0,0,1};
GLfloat position_s2[] = {-10,10,10,0};
W tej części zadania należało tak dobrać współczynniki RGB aby uzyskać odpowiedni efekt.
Dla materiału mamy zmienne: ambient, diffuse i specular, które określają kolejno składowe otoczenia, rozproszenia i lustrzaną światła. W zmiennej ambient ustalamy kolor, pozostałe parametry odpowiadają za ustawienia błyszczący/matowy. Aby uzyskać opowiedni rezultat , w materiale drugim należało ustawić małe wartości diffuse, a większe specular – dzięki temu otrzymujemy błyszczący materiał (dla pierwszego materiału odwotnie). Współczynniki do definiowania światła są podobne, jednak występują dodatkowo zmienne position i direction. position służy do określenia pozycji światła w przestrzeni, a direction to kierunek w jakim świeci światło.
Następnie należy napisać funkcje, które ustawiają materiały i światła według naszych ustawień.
void Material1() {
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_m1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_m1);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_m1);
glMaterialf (GL_FRONT, GL_SHININESS, 128);
}
void Material2() {
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_m2);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_m2);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_m2);
}
void Swiatlo1() {
glPushMatrix();
glRotatef(kat_x,1,0,0);
glRotatef(kat_z,0,0,1);
glTranslatef(0,R_L1,0);
glPushMatrix();
glPopMatrix();
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_s1);
glLightfv(GL_LIGHT1, GL_SPECULAR, specular_s1);
glLightfv(GL_LIGHT1, GL_POSITION, position_s1);
glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,direction_s1);
glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 1);
glPopMatrix();
}
void Swiatlo2() {
glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse_s2);
glLightfv(GL_LIGHT2, GL_SPECULAR, specular_s2);
glLightfv(GL_LIGHT2, GL_POSITION, position_s2);
}
void IloczynWektorowy() {
wektor3[0] = wektor1[1]*wektor2[2] - wektor2[1]*wektor1[2];
wektor3[1] = wektor1[2]*wektor2[0] - wektor2[2]*wektor1[0];
wektor3[2] = wektor1[0]*wektor2[1] - wektor2[0]*wektor1[1];
}
Takie definiowanie umożliwiają nam funkcje glMaterial() i glLight(). W funkcji światło znajdują się dodatkowo elementy odpowiedzialne za ruch reflektora.
Kolejnym etapem było zaprojektowanie połowy sfery . Funkcja realizujące to zadanie wygląda następująco:
void RysujSfere(double a)
{
float alfa = 0, teta = 0, x, y, z;
float R = 6, temp_y=0, temp_x=0, temp_z=0;
int licznik = 0, i=0, j=0;
const long double PI = 3.1415926535897932384621693993751058209;
angle=-PI/2;
//rysowanie domknięcia bryły
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0,0.0,0.0);
for(angle = 0.0f; angle <= (2.0f*PI);angle += (PI/64.0f))
{
x = R*cos(angle);
z = R*sin(angle);
glVertex3f(x, z, 0.0f) ;
}
glEnd();
//Sfera
for(i=0; i < poziom; i++)
{
if (i%2 == 0)
{licznik=1;}
else licznik=0;
for (j=0; j < pion; j++)
{
if (licznik%2 == 0)
{Material1();licznik=1;}
else {Material2();licznik=0;}
//rysowanie sfery
glBegin(GL_QUADS);
x = R*cos(-pi/2+(pi*j/pion))*cos(pi*i/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(pi*i/poziom);
glVertex3f(x,y,z);
temp_y = y;
temp_x = x;
temp_z = z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(pi*i/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(pi*i/poziom);
glVertex3f(x,y,z);
wektor1[0]= x - temp_x;
wektor1[1]= y - temp_y;
wektor1[2]= z - temp_z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(pi*(i+1)/poziom);
glVertex3f(x,y,z);
x = R*cos(-pi/2+(pi*j/pion))*cos(pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(pi*(i+1)/poziom);
glVertex3f(x,y,z);
wektor2[0]= x - temp_x;
wektor2[1]= y - temp_y;
wektor2[2]= z - temp_z;
IloczynWektorowy();
glNormal3f(wektor3[0],wektor3[1],wektor3[2]);
glEnd();
}
}
glPopMatrix();
Swiatlo1();
Swiatlo2();
}
Funkcja odpowiadająca za obsługę klawiatury:
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz){
case ';' : OBSERWATOR_ODLEGLOSC++;break;
case '.' : OBSERWATOR_ODLEGLOSC--;break;
case 'l' : OBSERWATOR_WYSOKOSC++;break;
case ',' : OBSERWATOR_WYSOKOSC--;break;
case 'k' : OBSERWATOR_OBROT_Y++;break;
case 'm' : OBSERWATOR_OBROT_Y--;break;
//PODZIAL - rownolezniki i poludniki
case '1' : poziom+=2;break;
case '2' : poziom-=2;break;
case '3' : pion+=2;break;
case '4' : pion-=2;break;
//Swiatlo
case 'q' : glEnable(GL_LIGHT0);break;
case 'w' : glDisable(GL_LIGHT0);break;
case 'e' : glEnable(GL_LIGHT1);break;
case 'r' : glDisable(GL_LIGHT1);break;
case 't' : glEnable(GL_LIGHT2);break;
case 'y' : glDisable(GL_LIGHT2);break;
//Regulowanie orbity L1
case 'a' : R_L1+=1;break;
case 'z' : R_L1-=1;break;
case 's' : kat_x++;break;
case 'x' : kat_x--;break;
case 'd' : kat_z++;break;
case 'c' : kat_z--;break;
case 27 : exit(0);break;
}
}
3.Wyniki działania programu.
4.Wnioski.
Celem zadań laboratoryjnych było zamodelowanie obiektu składającego się z dwóch różniących się materiałów, oświetlenie sceny dwoma odmiennymi źródłami światła, a następnie zaobserwowaniu relacji łączących te elementy i ich wpływ na otrzymywane efekty wizualne. Napisany program, doskonale ukazuje zasady powstawania barwy, oraz jej związek z właściwościami materiału tworzącego przedmiot, oraz światła na niego padającego. Zatem możemy stwierdzić, że cele zajęć zostały osiągnięte.