Download presentation
Presentation is loading. Please wait.
1
Hanyang University Jungsik Park
Implement of lighting Hanyang University Jungsik Park
2
Normal vector 조명효과를 적용하게 되면 조명과 폴리곤이 이루는 각도에 따라 물체의 색상이 다르게 표현되어야 한다.
폴리곤은 버텍스들의 집합으로 만들어지고, 폴리곤 내부의 색상은 폴리곤을 구성하는 버텍스 색상으로부터 계산되므로 버텍스마다 법선 벡터를 지정한다. 법선 벡터 지정함수 void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); void glNormal3fv (const GLfloat *v); 조명 효과 계산이 올바르게 수행되게 위해서는 법선 벡터는 단위 벡터로 지정되어야 한다. glEnable(GL_NORMALIZE); 를 사용하면 약간의 성능 저하가 발생하지만, 법선 벡터를 강제로 단위 법선 벡터로 변환하여 지정하게 된다.
3
Modified Phong model OpenGL에서 사용되는 조명 모델로 다음의 세 요소로 구성된다.
분산광(diffuse) 반사광(specular) 주변광(ambient) 빛의 세기 재질의 반사지수 I =kd Id l · n + ks Is (h · n )a + ka Ia 재질 표면의 반사율
4
조명 설정 조명 사용 glEnable(GL_LIGHTING); 전역 주변광 설정 void glLightModelfv (GLenum pname, const GLfloat *params); pname : 속성 종류 GL_LIGHT_MODEL_AMBIENT params : 속성값 배열(4차원 벡터 형태)
5
광원 설정 광원 설정 glEnable(GL_LIGHT0); 광원은 최소한 8개까지 설정 가능(GL_LIGHT0 ~ GL_LIGHT8) 광원의 속성 지정 void glLightfv (GLenum light, GLenum pname, const GLfloat *params); light : 광원의 이름 (GL_LIGHT0 ~ GL_LIGHT8) pname : 속성 종류 GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION params : 속성값 배열(4차원 벡터 형태) 빛의 세기값은 0~1사이의 값 광원 위치의 4번째 요소의 값이 0인 경우 배열 내의 벡터 방향으로 무한대 떨어진 곳에 광원이 위치
6
Example code - lightsource
#include <gl/glut.h> static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; static GLfloat xRotLight = 0.0f; static GLfloat yRotLight = 0.0f; static int width, height; GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f }; GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f }; GLfloat lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f }; bool bMoveLightSource = false; void SetProjection() { GLfloat fAspect = (GLfloat)width/(GLfloat)height; GLfloat nRange = height/4.0; if(height == 0) height = 1; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0f, fAspect, 1.0, 400.0); glMatrixMode(GL_MODELVIEW); } void ChangeSize(GLsizei w, GLsizei h) width = w; height = h; SetProjection(); void SpecialKeys(int key, int x, int y) { if (!bMoveLightSource) if(key == GLUT_KEY_UP) xRot-= 5.0f; if(key == GLUT_KEY_DOWN) xRot += 5.0f; if(key == GLUT_KEY_LEFT) yRot -= 5.0f; if(key == GLUT_KEY_RIGHT) yRot += 5.0f; xRot = (GLfloat)((const int)xRot % 360); yRot = (GLfloat)((const int)yRot % 360); } else if(key == GLUT_KEY_UP) xRotLight-= 5.0f; if(key == GLUT_KEY_DOWN) xRotLight += 5.0f; if(key == GLUT_KEY_LEFT) yRotLight -= 5.0f; if(key == GLUT_KEY_RIGHT) yRotLight += 5.0f; xRotLight = (GLfloat)((const int)xRotLight % 360); yRotLight = (GLfloat)((const int)yRotLight % 360); if (key == GLUT_KEY_F1) bMoveLightSource = !bMoveLightSource; glutPostRedisplay();
7
Example code - lightsource
void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, 0.0f, f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRotLight, 1.0f, 0.0f, 0.0f); glRotatef(yRotLight, 0.0f, 1.0f, 0.0f); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glPopMatrix(); // glColor로지정된색상은무시 glColor3f(1.0, 0.0, 0.0); glutSolidTeapot(100.0); glutSwapBuffers(); } oid SetupRC() { glEnable(GL_DEPTH_TEST); glCullFace(GL_BACK); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); glEnable(GL_LIGHT0); } int main(int argc, char *argv[]) glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 600); glutCreateWindow(“Light source"); glutReshapeFunc(ChangeSize); glutSpecialFunc(SpecialKeys); glutDisplayFunc(RenderScene); SetupRC(); glutMainLoop(); return 0;
8
실행 결과 glColor3f(1.0,0.0,0.0); 으로 모델 색상을 적색으로 지정하였지만, 무시되고 회색으로 그려졌다(광원의 diffuse 세기가 0.7,0.7,0.7이므로) 물체의 고유한 색상을 표현하기 위해서는 재질 속성을 지정해야 한다.
9
재질 속성 재질 속성 설정 void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); face : 폴리곤의 어떤 면에 대한 속성인지 지정. GL_FRONT, GL_BACK, GL_FRONT_AND_BACK pname : 속성 종류. GL_AMBIENT, GL_DIFFUSE, GL_EMISSION, GL_SPECULAR,GL_AMBIENT_AND_DIFFUSE params : 속성값 배열(4차원 벡터 형태) 반사율 값은 0~1사이의 값
10
Example code – material properties
다음을 전역 변수에 추가하고 GLfloat material[] = { 0.75f, 0.0, 0.0, 1.0f }; RenderScene() 함수를 다음과 같이 바꾼다. void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, 0.0f, f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRotLight, 1.0f, 0.0f, 0.0f); glRotatef(yRotLight, 0.0f, 1.0f, 0.0f); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material); glutSolidTeapot(100.0); glutSwapBuffers(); }
11
실행 결과
12
재질 속성 색상 트래킹(color tracking) 방법
버텍스 색상을 재질 속성으로 사용(ambient, diffuse) glEnable(GL_COLOR_MATERIAL); void glColorMaterial (GLenum face, GLenum mode); face : 폴리곤의 어떤 면에 대해 적용할지 지정 GL_FRONT, GL_BACK, GL_FRONT_AND_BACK mode : 어떤 속성이 버텍스 색상의 영향을 받을 것인지 지정 GL_EMISSION, GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_AMBIENT_AND_DIFFUSE 일반적으로 물체의 고유한 색상을 표현하기 위해 ambient 및 diffuse 성분은 색상 트래킹으로 지정하고, specular 성분은 따로 glMaterial3f를 이용하여 [1.0,1.0,1.0,1.0]과 같은 값을 지정.
13
Example code – color tracking
SetupRC()에 다음을 추가하고 glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); RenderScene() 함수를 다음과 같이 바꾼다. void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, 0.0f, f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRotLight, 1.0f, 0.0f, 0.0f); glRotatef(yRotLight, 0.0f, 1.0f, 0.0f); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glPopMatrix(); glColor3f(0.0, 1.0, 0.0); glutSolidTeapot(100.0); glutSwapBuffers(); }
15
재질 속성 재질의 반사지수 설정 Specular term ks Is (h · n )a 에서 α에 해당하는 값으로 하이라이트가 생기는 영역의 크기 void glMaterialf (GLenum face, GLenum pname, const GLfloat param); pname : 속성 종류 GL_SHINESS : 재질의 반사지수(specular exponent) parans : 속성값 반사지수의 경우 1 ~ 128 의 값. 작을수록 하이라이트의 면적이 넓어지고, 클수록 하이라이트 면적이 좁아진다.
16
Example code – specular highlight
다음을 전역 변수에 추가하고 GLfloat materialSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; RenderScene() 함수를 다음과 같이 바꾼다. void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, 0.0f, f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRotLight, 1.0f, 0.0f, 0.0f); glRotatef(yRotLight, 0.0f, 1.0f, 0.0f); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glPopMatrix(); glMaterialfv(GL_FRONT, GL_SPECULAR,materialSpecular); glMaterialf(GL_FRONT,GL_SHININESS,100); glColor3f(0.0, 1.0, 0.0); glutSolidTeapot(100.0); glutSwapBuffers(); }
17
실행 결과 GL_SHININESS를 100으로 지정할 경우 왼쪽 그림과 같이 specular highlight가 좁은 영역에 나타난다(붉은 원 표시된 부분, 시점에 따라 밝기가 다르다.). GL_SHININESS를 1로 지정한 경우 오른쪽 그림과 같이 specular highlight가 넓은 영역에 나타난다(h · n 가 한 번만 곱해지기 때문.).
18
Example code 직접 버텍스 좌표를 지정하여 모델링하는 경우 법선 벡터도 지정해 주어야 한다. 다읨의 코드를 추가하고,
void DrawCube() { glBegin(GL_QUADS); glNormal3f(0.0, 0.0, 1.0); glVertex3f(50.0,50.0,50.0); glVertex3f(50.0,-50.0,50.0); glVertex3f(-50.0,-50.0,50.0); glVertex3f(-50.0,50.0,50.0); glNormal3f(0.0, 0.0, -1.0); glVertex3f(50.0,50.0,-50.0); glVertex3f(-50.0,50.0,-50.0); glVertex3f(-50.0,-50.0,-50.0); glVertex3f(50.0,-50.0,-50.0); glNormal3f(0.0, 1.0, 0.0); glVertex3f(50.0,50.0,-50.0); glVertex3f(50.0,50.0,50.0); glVertex3f(-50.0,50.0,50.0); glVertex3f(-50.0,50.0,-50.0); glNormal3f(0.0, -1.0, 0.0); glVertex3f(50.0,-50.0,-50.0); glVertex3f(-50.0,-50.0,-50.0); glVertex3f(-50.0,-50.0,50.0); glVertex3f(50.0,-50.0,50.0); glNormal3f(1.0, 0.0, 0.0); glVertex3f(50.0,50.0,50.0);glVertex3f(50.0,50.0,-50.0); glVertex3f(50.0,-50.0,-50.0); glVertex3f(50.0,-50.0,50.0); glNormal3f(-1.0, 0.0, 0.0); glVertex3f(-50.0,50.0,50.0); glVertex3f(-50.0,-50.0,50.0); glVertex3f(-50.0,-50.0,-50.0); glVertex3f(-50.0,50.0,-50.0); glEnd(); } RenderScene()에서 glutSolidTeapot() 대신 DrawCube() 호출
19
Spot light 스포트라이트 조명의 설정을 위해서는 빛을 비추는 방향과 cut-off angle을 지정해야 한다.
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,angle); 도(degree) 단위의 cut-off angle 지정 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);
20
Example code - spotlight
전역 변수로 다음을 추가 GLfloat spotDir[] = { -lightPos[0],-lightPos[1],-lightPos[2], 1.0 }; 물체가 있는 곳을 비추기 위해 스포트라이트의 방향을 조명위치와 반대로 적용 SetupRC()에 다음을 추가 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f); SetupRC()에서 조명의 ambient 성분을 제거 RenderScene()에서 조명 위치를 지정하는 부분 다음에 다음을 추가 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);
21
실행결과 왼쪽 그림은 cut-off angle이 60도인 경우 오른쪽 그림은 cut-off angle이 10도인 경우
22
Shade model glShadeModel(GL_SMOOTH); glShadeModel(GL_FLAT);
Similar presentations