http://www.songho.ca/opengl/gl_projectionmatrix.html
OpenGL Projection Matrix
Overview
컴퓨터 모니터는 2D 평면이다. OpenGL에 의해 렌더링 되는 3D 장면은 컴퓨터 스크린에 2D 이미지로서 사영되어야만 한다. GL_PROJECTION 행렬은 이 사영 변환(projection transformation)을 위해 사용된다. 처음에, 그것은 모든 정점 데이터를 eye coordinates에서 clip coordinates로 변환한다. 그러고나서, 이러한 clip coordinates는 또한 clip coordinates의 w component로 나누어 normalized device coordinate (NDC)로 변환된다.
그러므로, 우리는 clipping (frustum culling)과 NDC transformations 둘 다 GL_PROJECTION matrix에 통합되어있다는 것을 명심해야만 한다. 다음의 섹션은 6개의 파라미터들 left, right, bottom, top, near 그리고 far boundary values로부터 projection matrix를 어떻게 구성하는지를 묘사한다.
w_c로 나누기 전에, frustum culling(clipping)이 clip coordinates에서 수행된다는 것을 주목해라. 그 clip 좌표들 x_c, y_c, z_c는 w_c와 비교하여 테스트된다. 만약 어떤 clip coordinates가 -w_c보다 작거나 또는 w_c보다 더 크다면, 그러면 그 정점은 버려져야만 한다.
그러고나서, OpenGL은 clipping이 발생하는 곳에서의 폴리곤의 edges를 재구성할 것이다.
Perspective Projection
perspective projection(원근 투영)에서, 길이가 줄여진 피라미드 frustum (eye coordinates)에 있는 한 3D 점은 한 정육면체 (NDC)로 사상된다; x 좌표의 범위는 [l,r] 에서 [-1,1]이고, y좌표의 범위는 [b,t] 에서 [-1, 1]이고, z좌표의 범위는 [n,f] -> [-1,1]이다.
eye coordinates가 오른손 좌표계로 정의된다는 것을 주목해라. 하지만, NDC는 왼손 좌표계를 사용한다. 즉, 원점에 있는 카메라는 eye space(view space)에서 -Z 축을 바라보고 있지만, NDC에서는 +Z축을 바라보고 있다. glFrustum()이 near과 far 거리의 양의 값만을 받기 때문에, 우리는 GL_PROJECTION 행렬을 구성하는 동안 그것들을 음수화 할 필요가 있다.
OpenGL에서, eye space에 있는 한 3D 점은 near plane (projection plane)으로 사영된다. 다음의 다이어그램들은 어떻게 eye space에 있는 한 점 (x_e, y_e, z_e)가 near plane에 있는 (x_p, y_p, z_p)로 사영되는지를 보여준다.
frustum의 top view에서, eye space의 x좌표인 x_e는 x_p로 사영되고, 이것은 비슷한 삼각형의 비율을 사용하여 계산된다;
frustum의 side view에서, y_p 또한 비슷한 방식으로 계산된다;
x_p와 y_p가 모두 z_e에 의존한다는 것을 주목해라; 그것들은 -z_e이의 역수에 비례한다. 다른 말로 하면, 그것들 둘 다 -z_e로 나눠진다. 그것이 GL_PROJECTION matrix를 구성하는 첫 번째 단서이다. eye coordinates가 GL_PROJECTION 행렬을 곱하여 변환된 후에, clip coordinates는 여전히 동차 좌표들이다. 그것은 clip coordinates의 w-component로 나누어 normalized device coordinates(NDC)가 된다. (OpenGL Transformation에서 좀 더 세부사항을 보아라)
그러므로, 우리는 clip coordinates의 w-component를 -z_e로 설정할 수 있다. 그래서, GL_PROJECTION 행렬의 4번째 행은 (0,0,-1,0)이 된다.
다음으로, 우리는 x_p와 y_p를 선형관계를 가진 NDC의 x_n과 y_n으로 사상시킨다; [l,r] =>[-1,1] and [b,t] => [-1,1].
그러고나서, 우리는 x_p와 y_p를 위의 방정식으로 치환한다.
우리가 각 방정식의 두 항이 perspective division (x_c_w_c, y_c/w_c)를 위해 나눠질 수 있도록 한 것을 주목해라. 그래서 우리는 w_c를 -z_e로 일찍 설정하고, 괄호안의 항들은 clip coordinates의 x_c와 y_c가 된다.
이러한 방정식들로부터 우리는 GL_PROJECTION matrix의 첫 번째와 두 번째 행을 알 수 있다.
이제 우리는 오직 GL_PROJECTION MATRIX만 풀면된다. z_n을 아는 것은 다른 것들과 조금 다르다. 왜냐하면 eye space에 있는 z_e는 항상 near plane에서 -n에 사영되기 때문이다. 그러나 우리는 clipping과 depth test를 위해 unique z value가 필요하다. 더해서, 우리는 그것을 unproject(inverse transform) 할 수 있어야 한다. 우리가 z가 x 또는 y값에 의존하지 않는 것을 알기 때문에, 우리는 z_n과 z_e 사이의 곤계를 찾기 위해 w_component를 가져온다. 그러므로, 우리는 GL_PROJECTION 행렬을 이렇게 명시할 수 있다.
eye space에서, w_e는 1과 같다. 그러므로, 그 방정식은 이렇게 된다.
A와 B 계수를 찾기 위해서, 우리는 (z_e, z_n) 관계를 사용한다; (-n, -1)과 (-f, 1), 그리고 그것들을 위의 방정식에 넣는다.
A와 B에 대해 방정식을 풀기 위해서, ... (소거법 실행)
우리는 A와 B를 찾았다. 그러므로, z_e와 z_n 사이의 관계는 다음과 같다.
마침내, 우리는 GL_PROJECTION 행렬의 모든 요소들을 찾았다. 그 복잡한 projection matrix는 다음과 같다.
이 projection matrix는 일반적인 frustum에 대한 것이다. 만약 viewing volume이 대칭이라면, r = -l 그리고 t = -b가 되고, 그것은 다음과 같이 간단하게 된다;
우리가 지나가기 전에, z_e와 z_n 사이의 관계의 방정식을 봐보자. 너는 그것이 유리 함수이고 z_e와 z_n사이가 비선형 관계라는 것을 알 수 있다. 이것은 near plane에서는 매우 높은 정밀도가 있지만, far plane에서 매우 낮은 정밀도가 있다는 것을 의미한다. 만약 [-n, -f]의 범위가 더 커진다면, 그것은 depth precision problem(z-fighting)을 야기시킨다; far plane 주변에서 z_e의 작은 변화가 z_n의 값에 영향을 미치지 않는다. n과 f 사이의 거리는 depth buffer precision 문제를 최소하기 위해 가능한한 짧아야만 한다.
Orthographic projection
orthographic projection을 위한 GL_PROJECTION을 구성하는 것은 perspective mode보다 더욱 간단하다.
모든 eye space에 있는 x_e, y_e, z_e가 NDC에 선형으로 사상된다. 우리는 그냥 한 rectangular cube를 정육면체로 스케일 할 필요가 있고, 그러고나서 그것을 원점으로 옮긴다. 선형 관계를 이용하여 GL_PROJECTION의 원소들을 찾아보자.
w-component가 orthographic projection에 필요하지 않기 때문에, GL_PROJECTION matrix는 (0,0,0,1)로 남게 된다. 그러므로, orthographic projection을 위한 완전하 GL_PROJECTION matrix는,
만약 viewing volume이 대칭이라면, 그것은 더 간단하게 될 수 있다. r = -l 그리고 t = -b이니.
댓글 없음:
댓글 쓰기