투상
: 3차원 물체를 화면으로 사상하기 위한 작업으로, 일명 가시 변환(Viewing Transformation) 이라고도 한다. 즉, 모델 좌표계, 전역 좌표계, 시점 좌표계를 순차적으로 거친 다각형 정점 좌표를 2차원 투상면으로 사상시키는 과정을 말한다. 

1. 평행투상
1) 졍규화 가시 부피에 의한 투상

- 가시부피
: 평행 투상에서, 제한된 크기의 뷰 윈도우에 모든 물체의 영상을 맺히게 할 수 없기 때문에 투상 범위를 항상 제한해야 한다. 이를 가시 부피라고 부른다. 

- void glOrtho(GLdouble left, GLdouble right, ,GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
: 평행 투상의 가시 부피 설정을 위한 함수다.
: near, far은 시점으로부터 절단면과의 거리다. 시점 좌표계는 오른손 법칙을 쓰기 때문에 near의 실제 z 좌표는 -near, far는 -far 이다.

- 가시 부피의 정규화 변환



: 가시 부피는 가로, 세로, 높이가 2인 정육면체로 투상하는 변환이다. 변환된 가시 부피를 정규화 가시 부피(Canonical View Volume)이라 한다. 
: 위 그림 에서 보듯이 변환 결과 시점 좌표계 원점은 정규화 가시 부피 정중앙에 위치한다. 여기서 유의할 점은 시점 좌표계가 오른손 법칙에서 왼속 법칙으로 바꼈다는 것이다. 
- 정규화 가시 부피를 사용하는 이유
1- 평행 투상, 원근 투상 모두 동일한 모습의 정규화 가시 부피를 사용함으로써 파이프라인 처리 구조가 동일해지기 때문이다.
2- 가시 부피 밖의 물체를 절단하는 데 있어서 정규화 가시 부피인 정육면체를 기준으로 하는 것이 훨씬 단순하기 때문이다.
3- 시점 좌표계 원점을 중심으로 가로, 세로 길이를 1로 정규화 함으로써 화면 좌표계로 변환하기가 수월해지기 때문이다.

- 정규화 변환 행렬
: 가시 부피를 물체로 간주하면, 이 물체의 중심을 위 그림 (b)에 표시된 정규화 가시 부피로 변환하기 위한 행렬은 다음과 같다.



glOrtho(left, right, bottom, top, near, far) 함수에 의해 내부적으로는 위 그림의 행렬이 현 투상 행렬로 올려지며 물체 정점에 곱해지게 된다. 

이 변환에 의해 가시 부피는 물론 가시 부피 내의 물체도 정규화 된다. 다시 말해 물체 정점 좌표가 바뀐다. 이 좌표계를 절단 좌표계(Clip Coordinate System)이라 부른다. 이는 정규화된 물체를 대상으로 이후에 가시 부피 밖의 물체에 대한 절단 작업이 가해지기 때문이다. 

2) GL의 투상
: 가시 부피를 정규화 가시 부피로 변환하고 범위를 벗어나는 물체들에 절단 작업이 가해진다. 그 후 2차원으로의 투상 작업이 가해진다. 2차원으로의 투상은 물체에 식 (7.3)의 행렬을 곱하는 것에 해당하며, 변환 결과 물체는 깊이 d=0인 투상면에 투상된다. 그러나 이 행렬을 곱하며 z값이 날아가 버리므로 이 작업은 깊이 정보를 활용한 이후로 미뤄진다.

* glMatrixMode(GL_PROJECTION); 함수로 투영 변환이라는 것을 명시
* 시스템마다 다르지만 투상 행렬 스택은 최소 2개 이상이다. 
* void glGetFloatv(GLenum pname, GLfloat *params);
: 현 투상 행렬 값 검색 함수.(pname에 "GL_PROJECTION_MATRIX" 넣어야 함, "GL_MODELVIEW_MATRiX" 넣으면 현 모델 뷰 행렬 값이 검색 됨.)

2. 원근 투상
1) 정규화 가시 부피에 의한 투상

평행 투상과 마찬가지로 GL의 원근 투상에서도 항상 투상 범위를 제한해야 한다. 



GL의 원근 투상의 가시 부피도 평행 투상과 동일한 모습의 정규화 가시 부피로 변환한다. 
일단 정규화 가시 부피로 바뀌면 GL은 평행 투상과 원근 투상을 동일한 방식으로 취급한다. 따라서 투상의 최종 단계인 3차원 정규화 가시 부피로부터 2차원 투상면으로의 투상은 단순히 z값을 무시하는 투상, 즉 평행투상이 된다. 

2) GL의 투상 함수 종류
void gluPerspective(GLdouble fov, GLdouble aspect, GLdouble near, GLdouble far);



파라미터 fov는 시야를 의미한다. 위 그림에서 보듯이 상하 y축 방향의 시야각을 나타낸 것으로 0~180도 범위를 갖는다. 
파라미터 aspect는 뷰 윈도우의 종횡비로, width/height 값이다. 물체 모습이 왜곡되는 것을 방지하려면 이 종횡비가 뷰 포트의 종횡비와 같아야 한다. 물론, x축 방향의 시야각을 fov와 종횡비에 의해 결정 된다.
파라미터 near, far는 전방, 후방 절단면의 위치값으로 항상 양수이어야 한다. 

시야각을 넓히는 것은 카메라로 말하자면 광각 렌즈를 끼우는 행위와 같다.



시야각을 좁히는 것은 망원 렌즈를 끼우는 행위와 같다. 

void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
: 파라미터 순서대로 가시 부피의 좌, 우, 상, 하, 전, 후가 정의된다.

3) 투상 파이프 라인

GL의 파이프라인 처리 순서를 설명해 보자.
1- 모델 변환
그림의 모델 행렬은 좌표계를 기준으로 하여 glScalef(), glRotatef(), glTranslatef()가 순차적으로 가해진 것이다. 이들 복합 변환을 모델 좌표계 기준의 물체 정점에 곱하면 전역 좌표계로 바뀐다. 

2- 시점 변환
gluLookAt()에 의해 할당된 뷰 행렬 V를 여기에 곱하면 시점 좌표계 기준으로 바뀐다.

3- 투상
이어서 투상 행렬을 적용해 3차원 좌표를 2차원 좌표에 투영 시킨다.

1단계 투상
: 투상 행렬을 시점 좌표에 곱하면 절단 좌표계라는 것으로 변한다. 그 후 가시 부피 바깥에 있는 부분을 절단한다.
* 절단 좌표계는 가시 부피 바깥에 있는 부분을 절단하기 쉽도록 변환된 좌표계 이다. 

2단계 투상 
: 절단 후 실제 정규 가시 부피로 투영된 3차원 좌표로 바꿔야 한다. 이 좌표를 정규화 장치 좌표계(Normalized Device Coordinates System)이라 한다. 
위 그림에서 보듯이 절단 좌표계와 정규화 장치 좌표계는 사실상 동일하다. 모두 정규화 가시 부피 내의 좌표를 정의하기 때문이다. 단지 차이점은 원근 분할을 하기 전인지, 후인지에 있다. 
원근 분할은 절단 좌표계에서 정규화 장치 좌표계로 전환하는 작업을 말한다. 

3단계 투상
: 정규화 가시 부피의 z=0 평면이 화면의 윈도우 또는 뷰 포트로 투상된다. 
3차원 정규화 장치 좌표를 2차원 뷰 포트로 투상하기 위해서는 z 성분만 없애면 되지만, 그 전에 깊이 정보가 활용되어야 한다. 





Posted by 홍성곤
,