Wojskowa Akademia Techniczna
Grafika komputerowa
Sprawozdanie
Z zajęć laboratoryjnych nr 4
Temat: Modelowanie oświetlenia.
Zwoliński Bartosz
I0Y2S1
Data wykonania ćwiczenia: 04.01.2012
I. Treść zadania:
Zadanie 19
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: żółty błyszczący (widziany w białym świetle),
Właściwości materiału nr 2: niebieski matowy (widziany w białym świetle),
Sposób przyporządkowania materiałów do obiektu zgodnie ze wzorem: szachownica z uwzględnieniem podziałów pionowych i poziomych.
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: biały,
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: żólty,
natężenie: 0.8,
położenie: stałe w punkcie P(10,10, 10) układu współrzędnych sceny.
kierunek świecenia: na obiekt.
Program powinien umożliwiać:
a) interaktywne, niezależne włączanie i wyłączanie źródeł światła;
b) interaktywną zmianę liczby podziałów pionowych i poziomych bryły;
c) interaktywną zmianę wielkości bryły;
d) interaktywną zmianę położenia obserwatora poprzez podanie następujących parametrów:
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
II. Wstęp:
Ze względów wydrukowania załączników w kolorze czarno-białym, umieszczam w sprawozdaniu kod źródłowy, na podstawie którego były robione screen'y. Kod źródłowy jest dowodem wykonania pracy, wyodrębniłem w nim(pogrubiona czcionka) macierze świateł oraz materiałów które były głównym zadaniem pracy laboratoryjnej, oraz umieściłem komentarze w kodzie dla najważniejszych elementów. Kod źródłowy zawiera poprawione błędy z pracy laboratoryjnej.
III. Kod Źródłowy:
#include <StdAfx.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <GL/glut.h>
#define M_PI 3.14159
#define dAlfa (360.0/N)
#define PROMIEN 1
// Makro przeliczajace stopnie na radiany
#define DEG2RAD(x) ((float)(x)*M_PI/180.0)
// Zmienne globalne
double N=6; //Podzialy poziome
double N2=6; //Podzialy pionowe
double r=PROMIEN; //Promien
//Zmienne odpowiedzialne za polozenie obserwatora
double katY = -20.0;
double katRX = 0.0;
double katRY = 0.0;
double katRZ = 0.0;
double katX = 20.0;
//Zmienne pomocnicze dla predkosci katowych zrodla swiatla.
double RX = 0.0;
double RZ= 0.0;
double RY= 0.0;
int obsR=15; //Odleglosc obserwatora
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int lightSwitch[2]={0,0};
int obrot;
float rRef=4;
GLfloat swiatlo[7][4];
GLfloat swiatlo2[7][4];
GLfloat material[6][4];
GLfloat material2[6][4];
void UstawDomyslneWartosciParametrow(void);
void WlaczOswietlenie(int, int);
void DefiniujMaterial(int);
void RysujWalec(double h, int nv, int nh);
void UstawParametryWidoku(int szer, int wys);
void RysujNakladke(void);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y);
void UstawDomyslneWartosciParametrow(void)
{
//Material pierwszy: żółty blyszczacy
GLfloat param_materialu[6][4] = {
{1.0, 1.0, 0.0, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.5, 0.5, 0.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{1.0, 1.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{128.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 0.0}}; // [4] kolor swiatla emitowanego
//Material drugi: niebieski matowy
GLfloat param_materialu2[6][4] = {
{0.0, 0.0, 1.0, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.0, 0.0, 1.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.0, 0.0, 0.2, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 0.0}}; // [4] kolor swiatla emitowanego
//Swiatlo pierwsze: Reflektor
GLfloat param_swiatla[5][4] = {
{0.0, 0.0, 0.0, 1.0}, // [0] otoczenie
{1.0, 1.0, 1.0, 1.0}, // [1] rozproszenie
{1.0, 1.0, 1.0, 1.0}, // [2] lustrzane
{0.0, 0.0, 0.0, 1.0}, // [3] polozenie
{0.0, 0.0, 0.0, 0.0}}; // [4] kierunek swiecenia
//Swiatlo drugie: Kierunkowe
GLfloat param_swiatla2[5][4] = {
{0.0, 0.0, 0.0, 1.0}, // [0] otoczenie
{1.0, 1.0, 0.0, 0.8}, // [1] rozproszenie
{1.0, 1.0, 0.0, 0.8}, // [2] lustrzane
{10.0, 10.0, 10.0, 1.0},// [3] polozenie
{0.0, 0.0, 0.0, 0.0}};// [4] kierunek swiecenia
memcpy(material, param_materialu, 5*4*sizeof(GLfloat));
memcpy(swiatlo, param_swiatla, 7*4*sizeof(GLfloat));
memcpy(material2, param_materialu2, 5*4*sizeof(GLfloat));
memcpy(swiatlo2, param_swiatla2, 7*4*sizeof(GLfloat));
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
void WlaczOswietlenie(int s1, int s2)
{
glEnable(GL_LIGHTING);
if (s1==1)
{
glEnable(GL_LIGHT0);
obrot=(obrot+5)%360;
obrot=45;
swiatlo[3][0]=rRef*cos(DEG2RAD(obrot));
swiatlo[3][1]=r/2;
swiatlo[3][2]=rRef*sin(DEG2RAD(obrot));
swiatlo[3][3]=1.0;
swiatlo[4][0]=-rRef*cos(DEG2RAD(obrot));
swiatlo[4][1]=-r/3;
swiatlo[4][2]=-rRef*sin(DEG2RAD(obrot));
swiatlo[4][3]=-1.0;
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo[2]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45); //kat odciecia
}
else glDisable(GL_LIGHT0);
if (s2==1)
{
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
}
else glDisable(GL_LIGHT1);
}
void DefiniujMaterial(int typ)
// Funckja umozliwiajaca wybor jednego z dwoch materialow.
{
if(typ==0)//Wybor materialu pierwszego.
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material[4]);
}
else //Wybor materialu drugiego.
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material2[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material2[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material2[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material2[4]);
}
}
void RysujSfere(int r) //Funkcja rysujaca 1/2 sfery
{
//zmienne pomocnicze
double m;
double j;
int i;
int zmienna=1;//zmienna odpowiedzialna za zmiane materialu
//Pomocniczy Uklad Wspolrzednych
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(-50.0, 0.0, 0.0);
glVertex3f(50.0, 0.0, 0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0, -20.0, 0.0);
glVertex3f(0.0, 20.0, 0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(0.0, 0.0, -20.0);
glVertex3f(0.0, 0.0, 20.0);
glEnd();
//Rysowanie kopuly sfery(funkcja z laboratoriow drugich z dodanymi wektorami normalnymi.
for(j=90.0; j>0.0; j=j-(90/N2)){
glBegin(GL_TRIANGLE_STRIP);
for(i=0; i*dAlfa<=360.0; i++){
DefiniujMaterial(zmienna); //Zmiana materialu w zaleznosci od wartosci "zmienna"
glNormal3f(sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), cos(DEG2RAD(j)), sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), (r)*cos(DEG2RAD(j)), r*sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
j=j-(90/N2);
glNormal3f(sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), cos(DEG2RAD(j)), sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), (r)*cos(DEG2RAD(j)), r*sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
j=j+(90/N2);
i++;
glNormal3f(sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), cos(DEG2RAD(j)), sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), (r)*cos(DEG2RAD(j)), r*sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
j=j-(90/N2);
glNormal3f(sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), cos(DEG2RAD(j)), sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j))*cos(DEG2RAD(i*dAlfa)), (r)*cos(DEG2RAD(j)), r*sin(DEG2RAD(j))*sin(DEG2RAD(i*dAlfa)));
j=j+(90/N2);
i--;
zmienna=!zmienna; //zmiana materialu w tym miejscu, pozwolila uzyskac szachownice
}
glEnd();
}
//Rysowanie podstawy kopuły(zamkniecie sfery)
glNormal3f(0.0, -1.0, 0.0);
for( m=0; m<N2;m++){
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.0,0.0,0.0);
for(i=0; i*dAlfa<=360.0; i++){
glVertex3f((r-(m*(r/N2)))*cos(DEG2RAD(i*dAlfa)), 0.0 , (r-(m*(r/N2)))*sin(DEG2RAD(i*dAlfa)));
glVertex3f((r-((m+1)*(r/N2)))*cos(DEG2RAD(i*dAlfa)), 0.0 ,(r-((m+1)*(r/N2)))*sin(DEG2RAD(i*dAlfa)));
}
glEnd();
}
}
void UstawParametryWidoku(int szer, int wys)
{
szerokoscOkna = szer;
wysokoscOkna = wys;
glViewport(0, 0, szerokoscOkna, wysokoscOkna);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, (float)szerokoscOkna/(float)wysokoscOkna, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void WyswietlObraz(void)
{
int j;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
UstawParametryWidoku(szerokoscOkna, wysokoscOkna);
WlaczOswietlenie(lightSwitch[0], lightSwitch[1]);
glTranslatef(0, 0, -obsR);
glRotatef(katX, 1, 0, 0);
glRotatef(katY, 0, 1, 0);
glPushMatrix();
glTranslatef(0.0, swiatlo[3][1], 0.0);
glRotatef(katRX, 1,0,0);
glRotatef(katRZ, 0,0,1);
glRotatef(katRY, 0,1,0);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
for(j=0; j<=360.0L; j++)
{
glVertex3f(rRef*sin(DEG2RAD(j)), 0.0,rRef*cos(DEG2RAD(j)));
glVertex3f(rRef*sin(DEG2RAD(j+1)), 0.0, rRef*cos(DEG2RAD(j+1)));
}
glEnd();
glTranslatef(swiatlo[3][0], 0.0, swiatlo[3][2]);
glutWireSphere(0.25, 20, 20); // Tworzenie sfery(wspolrzedne zrodla swiatla)
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo[4]);
glPopMatrix();
//Przypisania odpowiedzialne za predkosci katowe.
katRX = katRX+RX;
katRZ = katRZ+RZ;
katRY = katRY+RY;
RysujSfere(r);
glutSwapBuffers();
}
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
//podzialy PIONOWE
case ',':
if(N<64)
N=N+2;
break;
case '.':
if(N>4)
N=N-2;
break;
//podzialy POZIOME
case '[':
if(N2<64)
N2=N2+2;
break;
case ']':
if(N2>4)
N2=N2-2;
break;
//Wielkosc sfery
case '7':
r++;
break;
case '8':
if(r>1.0)
r=r--;
break;
//odleglosc obserwatora
case '+':
obsR++;
break;
case '-':
obsR--;
break;
//zmianna promienia orbity dla zrodla swiatla
case 'r':
rRef=rRef+0.1;
break;
case 'f':
rRef=rRef-0.1;
break;
//wlacznik i wylacznik swiatla1(reflektor)
case '1':
if (lightSwitch[0]==0) lightSwitch[0]=1;
else lightSwitch[0]=0;
break;
//wlacznik i wylacznik swiatla2(kierunkowe)
case '2':
if (lightSwitch[1]==0) lightSwitch[1]=1;
else lightSwitch[1]=0;
break;
//zmiana polozenia orbity zrodla swiatla(3 predkosci katowe, rozne osie)
case 'w':
if(RX>0.0)
RX=RX-0.1;
break;
case 's':
if(RX<0.3)
RX=RX+0.1;
break;
case 'a':
if(RZ>0.0)
RZ=RZ-0.1;
break;
case 'd':
if(RZ<0.3)
RZ=RZ+0.1;
break;
case 'z':
if(RY>0.0)
RY=RY-0.1;
break;
case 'x':
if(RY<0.3)
RY=RY+0.1;
break;
case 27:
exit(0);
}
}
void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y)
{
switch(klawisz)
{
//zmianna polozenia obserwatora
case GLUT_KEY_UP:
katX++;
break;
case GLUT_KEY_DOWN:
katX--;
break;
case GLUT_KEY_RIGHT:
katY++;
break;
case GLUT_KEY_LEFT:
katY--;
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
glutCreateWindow("Oswietlenie dla 1/2 sfery");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearDepth(1000.0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor (1.0, 1.0, 1.0, 1.0);
glutDisplayFunc(WyswietlObraz);
glutReshapeFunc(UstawParametryWidoku);
glutIdleFunc(WyswietlObraz);
glutKeyboardFunc(ObslugaKlawiatury);
glutSpecialFunc(ObslugaKlawiszySpecjalnych);
UstawDomyslneWartosciParametrow();
glutMainLoop();
return 0;
}
IV. Załączniki:
UWAGA: Dla potrzeb własnych zmieniłem wartość parametrów funkcji glClearColor na podana niżej:
„glClearColor (1.0f, 1.0f, 1.0f, 1.0f);” //kolor biały tła
-Zobrazowanie wszelkiego typu zmian położenia reflektora(wraz z zwiększanym i zmniejszanym promieniem jego orbity). Załączniki 1-4.
-Zobrazowanie wszelkiego typu zmian położenia obserwatora(wraz ze zmianami wielkości figury). Załączniki 5-8.
-Wszelkiego typu zmiany podziałów figury(liczba podziałów zawsze jest liczbą parzystą). Załączniki Załączniki 5-8.
V. Wnioski:
Mój sposób rozwiązania problemu, uwzględniający wszystkie warunki zadane w poleceniu, działa poprawianie. Wszelkie błędy wykonane podczas zajęć laboratoryjnych zostały rozwiązane i poprawnie zaimplementowane. Poznane nowe metody pracy nad grafiką, obejmujące głównie temat oświetlenia, bardzo dobrze uzupełniają wcześniejszy materiał. Do pracy podczas zajęć niezbędna była wiedza wyniesiona z poprzednich laboratoriów, na każdym kroku programu, programista musiał się wykazać przede wszystkim swoja wiedzą teoretyczną. Temat oświetlenia uważam za niezbędny przy pracy nad grafiką. Jedną z wad tego tematu jest, trudność wykonania, mimo swej wiedzy głównym składnikiem wykonania poprawnie pracy jest doświadczenie, dla osób nie posługujących się wcześniej systemem RGBA, bez podparcia jakimiś materiałami, zadanie byłoby nie wykonalne. Nie mniej jednak, dla osób posiadających wiedze z tego zakresu, wraz z czasem, praca przy oświetleniu wydaje się być wielkim atutem. Samo zamodelowanie to nie wszystko, nadanie figurze różnych właściwości oraz ustawienie oświetlenia, jest kluczowym elementem do nadania życia i realizmu dla grafiki. To czyni temat oświetlenia, a co za tym idzie umiejętności posługiwania się nim, jednym z najważniejszych elementów sceny.