카메라 설정의 필요성
정규 뷰 볼륨 (Canonical View Volume)
OpenGL의 기본 카메라 설정
x,y,z 정규화: [-1, +1] x [-1, +1] x [-1, +1]
정규화 시 하드웨어 세팅 및 개발에 용이함
OpenGL로 개발 시 최종으로 정규 뷰 볼륨에 들어가도록 해야함
왼손 좌표계 사용
View Frame을 Canonical View Volume으로 변환
([-1, +1] 공간 안에 들어가도록 변환)
촬영할 공간을 지정하여 클리핑
near clipping: 카메라에 가까이 있는 물체를 촬영에서 제외
far clipping: 카메라에서 너무 멀리 있는 물체를 촬영에서 제외
Projection Matrix Calculation
M_porj: Projection Transform 행렬
View Frame의 점 q_view를 Canonical View Volume으로 변환
- 전체 Transform 과정
qworld=Mmodelqmodelqview=Mviewqworldqproj=Mprojqview=MprojMviewMmodelqmodel
평행 프로젝션, 투사 프로젝션
Parallel Projection
모든 빛이 필름에 평행하게 들어와 장면이 만들어진다고 가정
- 직육면체 영역을 평행하게 Scaling
계산에 용이함
물체의 위치에 따른 크기의 변화가 없어보임
공학/건축 설계도 사용에 장점 (Isometric, Cabinet 프로젝션 등)
Perspective Projection
실제 카메라와 같이 원근감을 생각하여 빛이 피라미드 형태로 뻗어간다고 가정
- 점점 넓어지는 피라미드 영역
계산이 복잡함
원근감 표현 가능
소실점 (1-point, 2-point, 3-point 프로젝션)
Orthographic Projection
Parallel Projection의 일종
xyz 좌표축에 평행하게 직육면체 영역 설정
해당 영역을 그대로 Scaling하여 Canonical View Volume에 대응시킴
x: left ~ right
y: bottom ~ top
z: -zNear ~ -zFar
[xmin,xmax]×[ymin,ymax]×[zmin,zmax]→[−1,+1]×[−1,+1]×[−1,+1]
zNear, zFar 값의 설정
View Volume은 오른손 좌표계, Canonical View Volume은 왼손 좌표계
카메라를 기준으로 물체는 z축의 마이너스 값에 배치되어 있음
zNear와 zFar는 카메라로부터 거리를 나타내어 양수 값이므로 오른손 좌표계에선 z = -z_near, -z_far 평면으로 해석
(zmin=−znear)>(zmax=−zfar)
실제로는 z_min이 z_max보다 크지만 왼손 좌표계로 바뀌며 z축이 뒤집어져 정상적으로 매핑됨
2 Step Approach
- 직육면체 중앙의 좌표
(2xmax+xmin,2ymax+ymin,2zmax+zmin)
- 직육면체의 x축 길이
2xmax−xmin
- Orthographic Projection
- 직육면체의 중앙을 원점으로 평행이동
- x,y,z 방향으로 각자 길이가 2가 되도록 크기변환
Mproj=ST=⎣⎢⎢⎢⎡xmax−xmin20000ymax−ymin20000zmax−zmin200001⎦⎥⎥⎥⎤⎣⎢⎢⎢⎡100001000010−2xmax+xmin−2ymax+ymin−2zfar+znear1⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡xmax−xmin20000ymax−ymin20000zmax−zmin20−xmax−xminxmax+xmin−ymax−yminymax+ymin−zmax−zminzmax+zmin1⎦⎥⎥⎥⎤
직사각형 윈도우 프로그램
윈도우의 종횡비에 맞춰서 View Volume 설정 필요
최종 비율이 어떻게 나올지 모르므로 Canonical View Volume을 미리 비율에 맞추는 건 불가능
기존 프로그램에선 윈도우의 사이즈 변경 시 물체의 비율이 유지되지 않음
M_proj에서 비율을 보정해야함
-
좌표계 계산
화면비를 4:3으로 할 때 직사각형 범위
x: -1 ~ +1
y: -0.75 ~ +0.75
z: -1 ~ -3 (zNear: +1, zFar: +3)
-
vertex shader 프로그램
z-negate는 필요 없음, Projection Transform에서 함께 처리함
qproj=MprojMviewMmodelqmodel
#version 330 core
in vec4 aPos; // vertex position: attribute
in vec4 aColor; // vertex color: attribute
out vec4 vColor; // varying color: varying
uniform mat4 uModel; // model matrix: uniform
uniform mat4 uView; // view matrix: uniform
uniform mat4 uProj; // projection matrix: uniform
void main(void) {
gl_Position = uProj * uView * uModel * aPos; // transformation
vColor = aColor;
}
MVP: Model - View - Projection
void updateFunc(void) {
...
// viewing transform, (0,0,2)를 바라봄
matView = glm::lookAtRH(
glm::vec3( 0.0F, 0.0F, 2.0F ),
glm::vec3( 0.0F, 0.0F, 0.0F ),
glm::vec3( 0.0F, 1.0F, 0.0F )
);
// projection matrix, 4:3 화면비 적용
matProj = glm::orthoRH(
-1.0F, +1.0F,
-0.75F, +0.75F,
+1.0F, +3.0F // 좌표가 아닌 Distance 값
);
}
640x480 크기의 4:3 화면 비율에서 물체의 비율이 정상적으로 유지되어 출력하는 것을 확인
