블렌딩, 안티앨리어싱, 안개효과, 폴리곤오프셋

Download Report

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 #include static int leftFirst = GL_TRUE; /* 알파 블렌딩 함수 초기화 */ static void init(void) { glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel (GL_FLAT); glClearColor (0.0, 0.0, 0.0, 0.0); } 2011-2 학기 가상현실 11

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 #include #include #define MAXZ 8.0

#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 #include #include static float rotAngle = 0.; /* 알파 블렌딩, 힌트, 선분의 너비를 포함, RGBA 모드를 위한 * 안티앨리어싱 초기화, 선분의 너비입상(line width granularity)과 * 너비에 관해서 OpenGL의 구현에 따라 달라지는 내용 출력 */ void init(void) { GLfloat values[2]; glGetFloatv (GL_LINE_WIDTH_GRANULARITY, values); printf ("GL_LINE_WIDTH_GRANULARITY value is %3.1f\n", values[0]); 2011-2 학기 가상현실 33

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 #include #include #include static GLint fogMode; static void init(void) { GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 }; glEnable(GL_DEPTH_TEST); glLightfv(GL_LIGHT0, GL_POSITION, position); glEnable(GL_LIGHTING); 2011-2 학기 가상현실 45

{ 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 #include #include #ifdef GL_VERSION_1_1 GLuint list; GLint spinx = 0; GLint spiny = 0; GLfloat tdist = 0.0; GLfloat polyfactor = 1.0; GLfloat polyunits = 1.0; 2011-2 학기 가상현실 61

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