Transcript 블렌딩, 안티앨리어싱, 안개효과, 폴리곤오프셋
블렌딩 안티앨리어싱, 안개효과 그리고 폴리곤 오프셋
2011-2 학기 가상현실 1
내용
블렌딩 물체를 반투명하게 나타내는 기법 안티앨리어싱 가장자리를 부드럽게 처리 안개 효과 화면을 사실적으로 나타내는 기법 폴리곤 오프셋 교차되는 도형을 깔끔하게 나타냄 2011-2 학기 가상현실 2
블렌딩
블렌딩이 활성화 되어 있을 경우 알파값은 프레임 버퍼에 저장되어 있는 픽셀의 컬러와 프레그먼 트의 픽셀의 컬러값을 결합하는데 사용 블렌딩 연산은 장면이 레스터화되고, 프레그먼트로 전환된 후 프레 임버퍼의 마지막 픽셀이 그려지기 전에 수행 블렌딩을 하지 않으면 새로운 프레그먼트들은 프레임버퍼에 있는 기 존의 컬러값을 덮어쓰게 됨 프레그먼트의 RGB 성분은 컬러를 나타내고, 알파 성분은 투명도를 나타낸다고 생각 2011-2 학기 가상현실 3
입력값 요소와 기존값 요소 블렌딩을 하는 동안 프레그먼트의 컬러값과 현재 저장된 픽셀의 컬러값은 2단계의 과정을 거쳐 결합 입력값(source) 요소와 기존값(destination) 요소의 계산 방 식을 설정하고 입력값과 기존값을 서로 대응되는 요소들끼리 곱해줌 입력값과 기존값에 있는 RGBA값들을 더한다. (RsSr+RdDr, GsSg+GdDg, BsSb+BdDb, AsSa+AdDa) 2011-2 학기 가상현실 4
입력값 블렌딩 요소와 기존값 블렌딩 요소가 만들어지는 방법 두 개의 상수를 만들기 위해 glBlendFunc() 사용 두 가지 상수 중 하나는 입력값 요소가 계산되는 방법 결정 다른 하나는 기존값 요소가 계산되는 방법 결정 glEnable(GL_BLEND)로 활성화 기본값: GL_ONE(입력값), GL_ZERO(기존값) => 블렌딩 비활성화 void glBlendFunc(GLenum sfactor, GLenum dfacor); 프레그먼트에 있는 컬러값(입력값)과 프레임 버퍼에 있는 컬러값(기존 값)이 결합되는 방식을 설정 sfactor : 입력값의 블렌딩 요소를 계산하는 방법 dfactor : 기존 값의 블렌딩 요소가 계산되는 방법 각 요소들은 [0,1] 사이의 값을 가짐 결합된 입력값과 기존값의 컬러값도 [0, 1] 구간으로 클램프됨 2011-2 학기 가상현실 5
블 렌 딩
입력값 블렌딩 요소와 기존값 블렌딩 요소들 상수 GL_ZERO GL_ONE GL_DST_COLOR 관련 요소 입력값, 기존값 입력값, 기존값 입력값 GL_SRC_COLOR GL_ONE_MINUS_DST_ COLOR GL_ONE_MINUS_SRC_ COLOR GL_SRC_ALPHA 기존값 입력값 기존값 입력값. 기존값 계산된 블렌딩 요소 (0, 0, 0, 0) (1, 1, 1, 1) (Rd, Gd, Bd, Ad) (Rs, Gs, Bs, As) (1,1,1,1)-(Rd,Gd,Bd,Ad) (1,1,1,1)-(Rs,Gs,Bs,As) (As, As, As, As) 2011-2 학기 가상현실 6
블 렌 딩
GL_ONE_MINUS_SRC_A LPHA GL_DST_ALPHA 입력값, 기존값 입력값, 기존값 GL_ONE_MINUS_DST_A LPHA GL_SRC_ALPHA_SATUR ATE GL_CONSTANT_COLOR 입력값, 기존값 입력값 입력값, 기존값 GL_ONE_MINUS_CONST ANT_COLOR GL_CONSTANT_ALPHA 입력값, 기존값 입력값, 기존값 GL_ONE_MINUS_CONST ANT_ALPHA 입력값, 기존값 2011-2 학기 가상현실 (1,1,1,1)- (As, As, As, As) (Ad, Ad, Ad, Ad) (1,1,1,1)- (Ad, Ad, Ad, Ad) (f, f, f, 1); f=min(As,1 Ad) (Rc, Gc, Bc, Ac) (1,1,1,1)-(Rc,Gc,Bc,Ac) (Ac, Ac,Ac,Ac) (1,1,1,1)-(Ac,Ac,Ac,Ac) 7
블 렌 딩
블렌딩을 사용한 샘플들 입력값 요소와 기존값 요소의 모든 조합을 사용할 수 있는 건 아 님 대부분 응용 프로그램에서는 몇 가지 조합만 사용 하나의 이미지와 또 다른 이미지를 절반씩 그릴 때(두 이미지를 동등한 비율로 혼합하여 그릴 때) 입력값 요소를 GL_ONE으로, 기존값 요소를 GL_ZERO로 놓 고 첫번째 그림을 그린 후, 입력값 요소를 GL_SRC_ALPHA로 설정, 기존값 요소를 GL_ONE_MINUS_SRC_ALPHA로 설정, 알파값을 0.5로 놓고 두 번째 그림을 그림 첫 번째 그림을 0.75, 두 번째 그림을 0.25 정도의 비율로 섞 고 싶을 경우에는, 첫 번째 그림은 위와 동일하게, 두 번째 그 림은 알파값을 0.25로 설정하여 그림 2011-2 학기 가상현실 8
3개의 서로 다른 그림을 균일하게 섞고 싶은 경우 기존값 요소를 GL_ONE으로 설정, 입력값 요소를 GL_SRC_ALPHA로 설정 후 그림의 알파값을 0.3333333으로 똑같이 놓고 그림 현재 이미지에 관계 없이 브러쉬로 칠할 때 마다 색이 덧입혀지 도록 만들고 싶은 경우 10%의 알파값과 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA 이용, 브러쉬 이미지를 표현 블렌딩 함수의 입력값 요소로 GL_DST_COLOR 또는 GL_ONE_MINUS_DST_COLOR를 사용, 기존값 요소로 GL_SRC_COLOR 또는 GL_ONE_MINUS_SRC_COLOR를 사용 하면 각 컬러 요소들을 개별적으로 조절 가능 2011-2 학기 가상현실 9
3개의 반투명한 면으로 구성된 그림을 그릴 때 몇몇 오브젝트들 이 다른 오브젝트들을 가리고 있고, 모든 오브젝트들이 솔리드 배경 위에 놓여 있는 경우 가장 멀리 있는 면은 배경 컬러의 80%, 그 다음이 40%, 가장 가까운 면이 90% 컬러를 전달하려면 입력값 요소와 기존값 요소를 기본값으로 설정 블렌딩 요소의 입력값은 GL_SRC_ALPHA, 기존값은 GL_ONE_MINUS_SRC_ALPHA로 바꿈 알파값은 차례로 0.2, 0.6, 0.1로 설정 투명하게 처리해서 보이지 않게 만들려는 프레그먼트에 대해서 는 알파값을 0으로주고, 불투명한 프레그먼트에 대해서는 알파 값을 1.0으로 준다.
이런 식으로 이미지에 있는 개별적인 프레그먼트에 서로 다 른 알파값을 할당하면 직사각형이 아닌 래스터 이미지 효과 를 낼 수 있다.
2011-2 학기 가상현실 10
예제 6-1 블렌딩 예제 : alpha.c
서로 겹쳐진 두 개의 컬러 삼각형 include
static void drawLeftTriangle(void){ // draw a yellow triangle glBegin (GL_TRIANGLES); glColor4f(1.0, 1.0, 0.0, 0.75); glVertex3f(0.1, 0.9, 0.0); glVertex3f(0.1, 0.1, 0.0); glVertex3f(0.7, 0.5, 0.0); glEnd(); } static void drawRightTriangle(void){ // draw a cyan triangle glBegin (GL_TRIANGLES); glColor4f(0.0, 1.0, 1.0, 0.75); glVertex3f(0.9, 0.9, 0.0); glVertex3f(0.3, 0.5, 0.0); glVertex3f(0.9, 0.1, 0.0); glEnd(); } 2011-2 학기 가상현실 12
void display(void) { glClear(GL_COLOR_BUFFER_BIT); if (leftFirst) { drawLeftTriangle(); drawRightTriangle(); } else { drawRightTriangle(); drawLeftTriangle(); } } glFlush(); 2011-2 학기 가상현실 13
void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w); else gluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0); } 2011-2 학기 가상현실 14
void keyboard(unsigned char key, int x, int y){ switch (key) { case 't': case 'T': leftFirst = !leftFirst; glutPostRedisplay(); break; case 27: /* Escape key */ exit(0); break; default: break; } } 2011-2 학기 가상현실 15
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (200, 200); glutCreateWindow (argv[0]); init(); glutReshapeFunc (reshape); glutKeyboardFunc (keyboard); glutDisplayFunc (display); glutMainLoop(); return 0; } 2011-2 학기 가상현실 16
2011-2 학기 가상현실 17
깊이 버퍼를 이용한 3차원 블렌딩 폴리곤이 그려지는 순서는 블렌딩의 결과에 많은 영향을 미침 3차원의 반투명한 물체를 그릴 때는 앞에서부터 뒤로 그릴 것인지, 뒤에서부터 앞으로 그릴 것인지에 따라 다른 결과를 얻을 수 있음.
깊이버퍼에는 스크린의 윈도우상의 물체 중에서 주어진 픽셀이 차지하고 있는 부분과 시점 사이의 거리가 기록 한 화면에 불투명 오브젝트와 반투명 오브젝트 모두를 그릴 때는 불투명한 오브젝트의 뒤에 가려진 부분이 그려지지 않도록 깊이 버퍼를 사용 2011-2 학기 가상현실 18
반투명한 오브젝트가 가까이 있는 경우에는 불투명한 오브젝트 의 컬러와 블렌딩한다.
반투명한 오브젝트를 그리는 동안 깊이 버퍼를 활성화시키되 읽기 전용 상태로 둔다. glDepthMask() 함수 이용 인자로 GL_FALSE를 주면 버퍼는 읽기 전용, GL_TRUE 면 쓰기 가능 그리는 방법 먼저 깊이 버퍼를 사용하여 불투명한 오브젝트를 그린 후 깊이 버퍼를 읽기 전용 상태로 만들고, 반투명한 물체를 그리면서 불투명한 오브젝트의 깊이버퍼값과 비교함.
2011-2 학기 가상현실 19
예제 6-2 3차원 블렌딩: alpha3D.c
#include
#define MINZ -8.0
#define ZINC 0.4
static float solidZ = MAXZ; static float transparentZ = MINZ; static GLuint sphereList, cubeList; static void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 0.15 }; GLfloat mat_shininess[] = { 100.0 }; GLfloat position[] = { 0.5, 0.5, 1.0, 0.0 }; 2011-2 학기 가상현실 20
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); sphereList = glGenLists(1); glNewList(sphereList, GL_COMPILE); glutSolidSphere (0.4, 16, 16); glEndList(); } cubeList = glGenLists(1); glNewList(cubeList, GL_COMPILE); glutSolidCube (0.6); glEndList(); 2011-2 학기 가상현실 21
void display(void) { GLfloat mat_solid[] = { 0.75, 0.75, 0.0, 1.0 }; GLfloat mat_zero[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_transparent[] = { 0.0, 0.8, 0.8, 0.6 }; GLfloat mat_emission[] = { 0.0, 0.3, 0.3, 0.6 }; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glTranslatef (-0.15, -0.15, solidZ); glMaterialfv(GL_FRONT, GL_EMISSION, mat_zero); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_solid); glCallList (sphereList); glPopMatrix (); 2011-2 학기 가상현실 22
glPushMatrix (); glTranslatef (0.15, 0.15, transparentZ); glRotatef (15.0, 1.0, 1.0, 0.0); glRotatef (30.0, 0.0, 1.0, 0.0); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_transparent); glEnable (GL_BLEND); glDepthMask (GL_FALSE); // Depth 버퍼가 읽기전용 상태로 됨 glBlendFunc (GL_SRC_ALPHA, GL_ONE); glCallList (cubeList); glDepthMask (GL_TRUE); // Depth 버퍼가 쓰기전용 상태로 됨 glDisable (GL_BLEND); glPopMatrix (); } glutSwapBuffers(); 2011-2 학기 가상현실 23
void reshape(int w, int h) { glViewport(0, 0, (GLint) w, (GLint) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } 2011-2 학기 가상현실 24
void animate(void) { if (solidZ <= MINZ || transparentZ >= MAXZ) glutIdleFunc(NULL); else { solidZ -= ZINC; transparentZ += ZINC; glutPostRedisplay(); } } 2011-2 학기 가상현실 25
void keyboard(unsigned char key, int x, int y){ switch (key) { case 'a': case 'A': solidZ = MAXZ; transparentZ = MINZ; glutIdleFunc(animate); break; case 'r': case 'R': solidZ = MAXZ; transparentZ = MINZ; glutPostRedisplay(); break; case 27: exit(0); } } 2011-2 학기 가상현실 26
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB |GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow(argv[0]); init(); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutDisplayFunc(display); glutMainLoop(); return 0; } 2011-2 학기 가상현실 27
실행결과
2011-2 학기 가상현실 28
안티앨리어싱
수평이나 수직에 가까운 선들이 울퉁불퉁하게 보이는 것을 앨리어싱 이라 함 안티앨리어싱: 앨리어싱을 줄이는 방법 그림의 조각이 덮고 있는 픽셀 조각에 기초하여 각 프레그먼트에 대 한 적용범위(Coverage)를 계산한다.
RGBA 모드에서는 프레그먼트의 알파값과 적용범위값을 곱한다.
컬러인덱스모드에서는 프레그먼트 적용범위에 기초해서 컬러 인 덱스의 하위 4비트를 설정한다.
0000: 적용범위 없음 1111: 적용범위가 전체 2011-2 학기 가상현실 29
void glHint(GLenum target, GLenum hint) 이 함수는 OpenGL의 특정한 동작을 제어 적용범위의 계산은 복잡하고 OpenGL 구현마다 달라질 수 있으 므로 glHint()를 사용하여 제어 target : 제어할 동작을 나타냄 hint : 효율적으로 동작하도록 설정할 때 GL_FASTEST 지정 최고의 품질로 이미지 생성 때 GL_NICEST를 지정 별도로 지정하고 싶지 않을 때 GL_DONT_CARE 선택 2011-2 학기 가상현실 30
glHint()에서 사용하는 값들: target 인자값 매개변수 GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT GL__FOG_HINT 설명 안티앨리어싱 작업에서 점이나 선, 또는 다 각형의 샘플링 품질을 설정 GL_PERSPECTIVE_CORRECTION _HINT 안개 효과 계산이 픽셀마다 이루어지는지 (GL_NICEST),정점마다 이루어지는지 (GL_FASTEST) 여부를 설정 컬러와 텍스처 좌표 보간의 품질을 설정 2011-2 학기 가상현실 31
점과 선에 대한 안티앨리어싱 점이나 선을 안티앨리어싱 하려면 먼저 glEnable() 함수로 안티 앨리어싱 모드를 활성화 GL_POINT_SMOOTH 나 GL_LINE_SMOOTH 의 값을 선택함 glHInt()를 이용하여, 품질에 대한 힌트를 줄 수 있음 점의 크기나 선의 너비, 선의 모양 등 결정 RGBA 모드에서의 안티앨리어싱 RGBA모드에서는 블렌딩을 활성화 시켜야 함 입력값에 GL_SRC_ALPHA를 기존값에 GL_ONE_MUNUS_SRC_ALPHA를 사용.
선분이 조금 밝아지는 효과를 주기 위해서 기존값을 GL_ONE으로 설정 가능 2011-2 학기 가상현실 32
예제 6-3 안티앨리어싱 선분: aargb.c
안티앨리어싱 된 선분 [ 6 – 3 ] #include
glGetFloatv (GL_LINE_WIDTH_RANGE, values); printf ("GL_LINE_WIDTH_RANGE values are %3.1f %3.1f\n", values[0], values[1]); glEnable (GL_LINE_SMOOTH); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glLineWidth (1.5); } glClearColor(0.0, 0.0, 0.0, 0.0); 2011-2 학기 가상현실 34
void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f (0.0, 1.0, 0.0); glPushMatrix(); glRotatef(-rotAngle, 0.0, 0.0, 0.1); glBegin (GL_LINES); glVertex2f (-0.5, 0.5); glVertex2f (0.5, -0.5); glEnd (); glPopMatrix(); 2011-2 학기 가상현실 35
glColor3f (0.0, 0.0, 1.0); glPushMatrix(); glRotatef(rotAngle, 0.0, 0.0, 0.1); glBegin (GL_LINES); glVertex2f (0.5, 0.5); glVertex2f (-0.5, -0.5); glEnd (); glPopMatrix(); } glFlush(); 2011-2 학기 가상현실 36
void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) gluOrtho2D (-1.0, 1.0, -1.0*(GLfloat)h/(GLfloat)w, 1.0*(GLfloat)h/(GLfloat)w); else gluOrtho2D (-1.0*(GLfloat)w/(GLfloat)h, 1.0*(GLfloat)w/(GLfloat)h, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } 2011-2 학기 가상현실 37
void keyboard(unsigned char key, int x, int y) { switch (key) { case 'r': case 'R': rotAngle += 20.; if (rotAngle >= 360.) rotAngle = 0.; glutPostRedisplay(); break; case 27: /* Escape Key */ exit(0); break; default: break; } } 2011-2 학기 가상현실 38
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (200, 200); glutCreateWindow (argv[0]); init(); glutReshapeFunc (reshape); glutKeyboardFunc (keyboard); glutDisplayFunc (display); glutMainLoop(); return 0; } 2011-2 학기 가상현실 39
2011-2 학기 가상현실 40
컬러 인덱스 모드에서의 안티앨리어싱 컬러 인덱스 모드에서 안티 앨리어싱을 적용할 때 가장 까다로운 부분은 컬러 맵을 읽어오고 사용하는 부분 컬러 인덱스의 마지막 4비트가 적용 범위값을 나타내기 때문에 배경 컬러에서 오브젝트 컬러까지 16개의 인덱스를 컬러 램프에 읽어 와야 함 램프에 있는 처음 16컬러로 컬러 버퍼를 초기화 한 다음, 이 램 프에 있는 컬러를 사용하여 점과 선을 그림 2011-2 학기 가상현실 41
안티앨리어싱을 적용한 폴리곤 내부가 채워진 폴리곤을 안티앨리어싱 하는 원리는 점이나 선을 안티앨리어싱 하는 것과 비슷 폴리곤들 모서리가 서로 중첩될 때는 컬러 값을 적절하게 블렌딩 RGBA 모드에서 안티앨리어싱을 하기 위해서는 폴리곤 가장자리 의 적용 범위값을 알파값으로 사용.
폴리곤에 대해 안티앨리어싱을 적용하려면 glEnable()의 인자로 GL_POLYGON_SMOOTH를 넘겨줌 2011-2 학기 가상현실 42
안 개 효 과
이미지가 너무 날카롭거나 부자연스럽게 보이는 경우를 보완 안티앨리어싱으로 오브젝트의 모서리를 부드럽게 다듬어 오브젝 트가 좀더 사실적으로 보이도록 만들기 가능 안개 효과 함께 이용, 전반적인 이미지를 더욱 자연스럽게 표현 안개효과가 활성화 되면 시점으로부터 멀리 떨어져 있는 물체는 안 개효과 컬러로 서서히 흐려짐 안개 효과는 행렬변환, 라이팅, 텍스처매핑이 끝난 뒤에 적용됨 점과 선을 포함한 모든 종류의 기하 프리미티브에 적용될 수 있다. 점과 선에 안개효과를 적용한 것을 Depth-cuing 이라고 부름 2011-2 학기 가상현실 43
안개 효과 사용하기 glEnable() 인자로 GL_FOG 넘겨줌 glFog()를 이용, 안개의 컬러와 밀도를 결정할 방정식을 선택 예) glFogi(GL_FOG_MODE, GL_LINEAR); 필요에 따라 glHint()로 GL_FOG_HINT의 값을 설정할 수도 있다.
2011-2 학기 가상현실 44
예제 6-5 RGBA 에서 안개 효과를 적용하여 그린 다섯 개의 구: fog.c
#include
{ glEnable(GL_LIGHT0); GLfloat mat[3] = {0.1745, 0.01175, 0.01175}; glMaterialfv (GL_FRONT, GL_AMBIENT, mat); mat[0] = 0.61424; mat[1] = 0.04136; mat[2] = 0.04136; glMaterialfv (GL_FRONT, GL_DIFFUSE, mat); mat[0] = 0.727811; mat[1] = 0.626959; mat[2] = 0.626959; glMaterialfv (GL_FRONT, GL_SPECULAR, mat); glMaterialf (GL_FRONT, GL_SHININESS, 0.6*128.0); } 2011-2 학기 가상현실 46
glEnable(GL_FOG); { GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0}; } fogMode = GL_EXP; glFogi (GL_FOG_MODE, fogMode); glFogfv (GL_FOG_COLOR, fogColor); glFogf (GL_FOG_DENSITY, 0.35); glHint (GL_FOG_HINT, GL_DONT_CARE); glFogf (GL_FOG_START, 1.0); glFogf (GL_FOG_END, 5.0); } glClearColor(0.5, 0.5, 0.5, 1.0); /* fog color */ 2011-2 학기 가상현실 47
static void renderSphere (GLfloat x, GLfloat y, GLfloat z){ glPushMatrix(); glTranslatef (x, y, z); glutSolidSphere(0.4, 16, 16); glPopMatrix(); } void display(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); renderSphere (-2., -0.5, -1.0); renderSphere (-1., -0.5, -2.0); renderSphere (0., -0.5, -3.0); renderSphere (1., -0.5, -4.0); renderSphere (2., -0.5, -5.0); glFlush(); } 2011-2 학기 가상현실 48
void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-2.5, 2.5, -2.5*(GLfloat)h/(GLfloat)w, 2.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-2.5*(GLfloat)w/(GLfloat)h, 2.5*(GLfloat)w/(GLfloat)h, -2.5, 2.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity (); } 2011-2 학기 가상현실 49
void keyboard(unsigned char key, int x, int y) { switch (key) { case 'f': case 'F': if (fogMode == GL_EXP) { fogMode = GL_EXP2; printf ("Fog mode is GL_EXP2\n"); } else if (fogMode == GL_EXP2) { fogMode = GL_LINEAR; printf ("Fog mode is GL_LINEAR\n"); } 2011-2 학기 가상현실 50
} else if (fogMode == GL_LINEAR) { fogMode = GL_EXP; printf ("Fog mode is GL_EXP\n"); } glFogi (GL_FOG_MODE, fogMode); glutPostRedisplay(); break; case 27: exit(0); break; default: break; } 2011-2 학기 가상현실 51
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow(argv[0]); init(); glutReshapeFunc (reshape); glutKeyboardFunc (keyboard); glutDisplayFunc (display); glutMainLoop(); return 0; } 2011-2 학기 가상현실 52
실행결과
2011-2 학기 가상현실 53
안개 효과 방정식 void glFog{if}(Glenum pname, TYPE param); void glFog{if}v(Glenum pname, TYPE *params); 이 함수들은 안개 효과를 계산하기 위한 매개변수 방정식 설 정 pname 을 GL_FOG_MODE로 설정할 경우 param은 GL_EXP, GL_EXP2, GL_LINEAR 중에서 설정 2011-2 학기 가상현실 54
RGBA 모드에서 안개 효과 RGBA 모드에서는 안개 효과 요소 f를 다음과 같이 최종적인 안 개 효과의 컬러를 결정하는 데 사용 C = fCi + (1 – f)Cf f: 안개효과 요소 Ci : 입력된 프레그먼트의 RGBA 값을 나타냄 Cf : GL_FOG_COLOR로 설정된 안개 효과 컬러값을 나 타냄 2011-2 학기 가상현실 55
컬러 인덱스 모드에서의 안개 효과 컬러 인덱스 모드에서의 최종적인 안개 효과는 컬러는 다음과 같 은 공식으로 계산 I = Ii + (1 – f) If Ii : 는 입력된 프레그먼트의 컬러 인덱스를 나타냄 If : GL_FOG_INDEX 설정된 안개 효과의 컬러 인덱스를 나타 냄 컬러 인덱스 모드에서 안개 효과를 사용하려면 컬러 램프에 적절 한 값을 넣어야 한다.
2011-2 학기 가상현실 56
폴리곤 오프셋
솔리드 오브젝트의 모서리를 하이라이트 처리하려면 오브젝트를 GL_FILL 모드로 그린 후 다른 컬러로 GL_LINE 모드 에서 다시 한 번 그려주어야 함 선분과 폴리곤은 정확히 동일한 방식으로 래스터화 되지 않음. 그래 서 선분의 깊이값과 폴리곤 모서리 깊이값이 서로 다름 이 때문에 선분이 도형의 위에서 사라졌다 나타났다 하는 현상이 발생(스티칭 현상) 이러한 어색한 효과를 없애주기 위해서 폴리곤 오프셋 이용 모서리를 하이라이트 선분과 깨끗하게 분리 2011-2 학기 가상현실 57
오프셋은 폴리곤을 래스터하는 3가지 방법에 따라 활성화 GL_FILL, GL_LINE, GL_POINT glEnableI()의 인자로 GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET, GL_POLYGON_OFFSET_POINT 으로 모 드를 활성화 void glPolygonOffset(GLfloat factor, GLfoat units); 폴리곤 오프셋이 활성화되어 있을 때 각각 프레그먼트의 깊이값 을 계산된 오프셋값에 더한다. 2011-2 학기 가상현실 58
계산된 오프셋값 o = m*factor + r*units m: 다각형의 최대 깊이 경사값(maximum depth slope) r: OpenGL 구현에 따라 다름 깊이경사값 폴리곤을 가로지르는 선분의 z값의 변화량을 x와 y값의 변화량으로 나 눈 값을 말한다.
깊이값은 윈도우 좌표계의 값으로 계산되고 [0, 1] 구간으로 클램프된 다.
near 클리핑 평면과 far 클리핑 평면에 평행한 폴리곤은 깊이 경사가 0 이된다. 깊이 경사가 0에 가까운 폴리곤들은 작은 상수 오프셋으로 충분 하며, glPolygonOffset()의 인자로 factor=0.0, unit=1.0으로 전달 클리핑 평면에 대해 큰 각도를 갖는 도형(깊이 경사값이 0보다 큰 도형) 은 큰 오프셋이 필요 0이 아닌 작은 값, 즉 0.75나 1.0 같은 값들을 이용 2011-2 학기 가상현실 59
예제: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); glCallList(list); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glColor3f(1.0, 1.0, 1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glCallList(list); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 2011-2 학기 가상현실 60
예제 6-7 눈에 띄는 결함을 없애는 다각형 오 프셋: polyoff.c
#include
void display (void) { GLfloat mat_ambient[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat mat_diffuse[] = { 1.0, 0.0, 0.5, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat gray[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 }; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glTranslatef (0.0, 0.0, tdist); glRotatef ((GLfloat) spinx, 1.0, 0.0, 0.0); glRotatef ((GLfloat) spiny, 0.0, 1.0, 0.0); 2011-2 학기 가상현실 62
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray); glMaterialfv(GL_FRONT, GL_SPECULAR, black); glMaterialf(GL_FRONT, GL_SHININESS, 0.0); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(polyfactor, polyunits); glCallList (list); glDisable(GL_POLYGON_OFFSET_FILL); 2011-2 학기 가상현실 63
glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glColor3f (1.0, 1.0, 1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glCallList (list); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } glPopMatrix (); glFlush (); 2011-2 학기 가상현실 64
void gfxinit (void) { GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat global_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; glClearColor (0.0, 0.0, 0.0, 1.0); list = glGenLists(1); glNewList (list, GL_COMPILE); glutSolidSphere(1.0, 20, 12); glEndList (); 2011-2 학기 가상현실 65
glEnable(GL_DEPTH_TEST); } glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glLightModelfv (GL_LIGHT_MODEL_AMBIENT, global_ambient); 2011-2 학기 가상현실 66
void reshape(int width, int height) { glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective(45.0, (GLdouble)width/(GLdouble)height, 1.0, 10.0); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } 2011-2 학기 가상현실 67
void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: switch (state) { case GLUT_DOWN: spinx = (spinx + 5) % 360; glutPostRedisplay(); break; default: break; } break; 2011-2 학기 가상현실 68
case GLUT_MIDDLE_BUTTON: switch (state) { case GLUT_DOWN: spiny = (spiny + 5) % 360; glutPostRedisplay(); break; default: break; } break; 2011-2 학기 가상현실 69
} case GLUT_RIGHT_BUTTON: switch (state) { case GLUT_UP: exit(0); break; default: break; } break; default: break; } 2011-2 학기 가상현실 70
void keyboard (unsigned char key, int x, int y) { switch (key) { case 't': if (tdist < 4.0) { tdist = (tdist + 0.5); glutPostRedisplay(); } break; case 'T': if (tdist > -5.0) { tdist = (tdist - 0.5); glutPostRedisplay(); } break; 2011-2 학기 가상현실 71
case 'F': polyfactor = polyfactor + 0.1; printf ("polyfactor is %f\n", polyfactor); glutPostRedisplay(); break; case 'f': polyfactor = polyfactor - 0.1; printf ("polyfactor is %f\n", polyfactor); glutPostRedisplay(); break; 2011-2 학기 가상현실 72
} case 'U': polyunits = polyunits + 1.0; printf ("polyunits is %f\n", polyunits); glutPostRedisplay(); break; case 'u': polyunits = polyunits - 1.0; printf ("polyunits is %f\n", polyunits); glutPostRedisplay(); break; default: break; } 2011-2 학기 가상현실 73
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow(argv[0]); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMouseFunc(mouse); glutKeyboardFunc(keyboard); gfxinit(); glutMainLoop(); return 0; } 2011-2 학기 가상현실 74
#else int main(int argc, char** argv) { fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n"); fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n"); fprintf (stderr, "you may be able to modify this program to make it run.\n"); return 0; } #endif 2011-2 학기 가상현실 75
실행 결과
2011-2 학기 가상현실 76