Chapter 2 : 정점 처리

코승호딩·2022년 9월 15일
0

게임수학

목록 보기
2/3
post-thumbnail

📌렌더링 파이프라인

렌더링 파이프라인의 단계

파이프라인이란 작업이 순차적으로 수도관마냥 수행되는 것을 의미한다.
우리의 목적은 변환 파이프라인을 통해 3D 모델 좌표를 2D 화면 좌표(픽셀)로 변환할 수 있어야 한다.

정점 처리
렌더링 파이프라인에서 가장 먼저 해야하는 일로 모델의 정점이 가지고 있는 정보(정점 버퍼)의 정점에 대한 변환(transformation)등의 연산을 수행하고 있는 것이다.
변환은 모델에 어떤 정보가 있냐에 따라 정점 처리의 방법이 달라질 수 있다.

래스터화
두 번째 단계로 래스터화는 정점 처리 단계를 통해 변환된 정점을 가지고 폴리곤(다각형)을 만들고 그 다각형을 구성하고 있는 내부의 모든 픽셀을 찾아 색을 결정하는 과정이다.
폴리곤을 구성하고 있는 픽셀들을 찾고 각각의 픽셀들은 정점이 갖고 있는 정보들을 그대로 갖고 있는 형태로 처리가 되기 때문에 이 데이터 모음을 프래그먼트라 한다.

프래그먼트 처리
각각의 프래그먼트에 대해서 텍스쳐링 등의 작업을 거쳐 최종적으로 색상을 결정하는 단계로 픽셀 셰이더, 프래그먼ㅌ 셰이더에서 보통 처리된다.

출력 병합
현재 출력해야 하는 픽셀과 이미 화면에 있는 색깔을 결합하거나 선택하여 최종적으로 컬러 버퍼를 수정하여 출력 하는 단계이다.

프래그먼트 : 각 픽셀의 위치에 정점이 가지고 있는 정보를 갖게 하도록 만든 데이터의 모음

컬러 버퍼(프레임 버퍼) : 화면을 그리기 위한 대상의 그래픽 메모리로 화면을 구성하는 픽셀 전체가 저장되는 메모리 공간이다.


프로그래밍 가능 단계

정점 처리와 프래그먼트 처리가 일어난다.
정점 셰이더에서는 정점에 대한 변환이 일어나며 프래그먼트 셰이더 또는 픽셀 셰이더에서는 프래그먼트 색상을 결정하는 과정을 거친다. 위 그림에서 파란색 부분에 해당한다.

하드웨어로 고정된 단계

고정 파이프라인 단계로 정점들에 대한 정보를 가지고 화면에 그려져야 하는 픽셀을 찾고 이 픽셀들의 정보를 정점의 정보로부터 구해내는 과정이 래스터화 단계이다. 래스터화 단계와 출력 병합 단계가 고정 파이프라인 단계에 해당한다. 위 그림에서 주황색 부분에 해당한다.

정점 셰이더, 프래그먼트 셰이더, 픽셀 셰이더는 프로그래머가 함수 자체를 만들어서 설정할 수 있기 때문에 완전히 프로그래머의 표현에 따라 달라질 수 있는 단계이다.
고정 파이프라인 단계는 라이브러리가 만들어 놓은 코드를 입출력, 파라미터를 어떻게 하냐에 따라 동작이 달라지는 단계이다.


📌정점 처리

정점 처리에서는 가장 기본적으로 변환(Transform)을 처리하고 드물게 조명(Lighting)을 처리하기도 하며 애니메이션(Animation)처리를 할 수 있다.


변환(Transform)


정점에 대한 변환은 첫 번째로 월드 변환(World transform), 두 번째로 뷰 변환(View transform), 세 번째로 투영 변환(Projection transform) 마지막으로 스크린 변환(Screen transform)으로 총 4단계에 거쳐 변환이 이루어 진다.

간단히 요약하여 모델이 가지고 있는 모델 스페이스를 월드 변환을 통해 게임 세상에 배치하고 게임 세상에 배치된 모델들을 카메라 기준의 공간으로 배치하기 위하여 뷰 변환을 진행하고, 게임 세상 속 3D 물체들을 2D 화면으로 투영시키기 위한 투영 변환을 거쳐 마지막으로 플레이어가 스크린을 볼 때와 같이 적절한 스크린을 보여주기 위한 스크린 변환을 단계로 순차적으로 이뤄진다. 행렬 계산이기 때문에 한 번에 계산이 가능하다.


아핀변환

한 벡터 공간을 다른 벡터 공간에 대응시키고 직선과 거리의 비를 보존하는 변환으로 선형 변환(축소/확대, 회전), 이동 변환이 있다. 이동 변환은 선형 변환이 아니다.
쉽게 말해, 아핀 변환은 선형 변환과 이동 변환을 한차원 더 높은 좌표계를 사용하여 한 번에 표현할 수 있는 변환이다.


2D 회전(Rotation)


2D에서는 2x2행렬로 다음과 같이 회전을 나타낼 수 있다.
공식 자체는 중요한 것이 아니기 때문에 개념만 알아두자.


3D 회전(Rotation)


다음과 같이 0과 1로 표현된 축이 회전 축이다.
이도 모두 라이브러리에서 제공을 하니 자체를 암기할 필요는 없다. 대신 회전 공식의 의미를 이해하자.


평행 이동(Translation)


선형대수학에서 배웠다시피 행렬의 이동은 단순히 행렬의 덧셈으로 나타낼 수 없다. 평행이동은 선형 변환이 아니기 때문이다. 3x3행렬에서 이동 변환을 하기 위해서는 동차좌표를 이용해 3차원을 4차원의 행렬로 만들어준 후 행렬의 곱셈으로 표현을 해야만 한다.

행벡터일 경우와 열벡터일 경우 다르기 때문에 열벡터일 경우는 이동할 좌표를 4열에 나열하고 행벡터일 경우에는 4행에 나열해야 한다.


동차 좌표계(Homogenous Coordinates)


w의 값이 0이면 벡터를 의미하고 1이면 점 위치 벡터를 나타낸다. w의 값이 0일 경우 벡터에 4x4 행렬을 곱하여도 이동 변환에 대한 정보는 변환의 결과에 영향을 끼치지 않는다. 따라서 (x, y, z, 0)은 방향 벡터를 의미하며 (x, y, z, 1)은 위치 벡터를 나타내게 된다.


월드 변환(World)

물체는 자신의 오브젝트 공간(Object space = Model space) 에서 고정불변의 좌표를 가지며 이 물체를 게임 세상에서 어떤 위치에 어떤 방향으로 배치를 하기 위해서는 월드 좌표계라 부르는 World space 좌표계가 필요하다.

쉽게 말해 마야나 맥스와 같은 모델링 프로그램을 통해 만든 모델들은 자신들 만의 모델 스페이스가 있을 것이고 이 모델들을 게임 세상에 배치하기 위한 새로운 좌표인 월드 좌표계로 변환을 해줘야 한다는 것이다.


위 행렬식은 (0, 1, 0, 1) 즉, x = 0, y = 1, z = 0 의 월드 스페이스에 해당하는 모델에 4x4행렬을 곱하여 2배만큼 스케일을 키워준 행렬 변환이다.
이동 변환에 해당하는 주황색 부분이 0이기 때문에 w의 값이 1에 해당하더라도 움직임이 없어 이동은 하지 않는다는 것을 볼 수 있다.

예제) 그러면 만약 다음 그림과 같이 (0, 2, 3)의 월드 스페이스를 가진 주전자를 (10, 2, 0)의 월드 스페이스로 변환하기 위해서는 어떠한 행렬 계산을 해줘야 할까?
-> 우선 SRT의 변환을 생각해보자
주전자의 스케일은 달라지지 않았고 다음으로 주전자의 로테이션은 정확히 y를 축으로 90만큼 회전 변환 하였다. 오른손 좌표계를 기준으로 y축 방향은 반시계방향으로 갈수록 +가 되기 때문에 세타 값에 90을 넣어줘야 한다. 따라서 그림에서 두번째에 해당하는 변환을 세타값 90을 넣어 4x4행렬을 (0, 2, 3, 1)에 곱해주게 되면 (3, 2, 0, 1)이라는 행렬을 얻을 수 있다.
다음 주전자는 x축의 방향으로 7만큼 이동했으니 4x4 단위 행렬에 맨 오른쪽 x의 이동 변환에 해당하는 4열 1행에 7을 대입해주고 이를 (3, 2, 0, 1)의 월드 스페이스에 곱해주게 되면 정확히 (10, 2, 0, 1)의 좌표를 얻을 수 있다.

앞서 설명했듯이 STR의 순서만 잘 지켜 행렬을 계산해준다면 위 예제에서 로테이션과 이동 변환의 행렬 계산을 한 번에 할 수 있을 것이다.

행렬 변환을 할 때 꼭 지켜야 할 점이 있는데 바로 SRT라는 순서를 지켜야 한다.
1. Scale을 먼저 계산
2. Rotation을 다음으로 계산
3. 마지막으로 Translation을 계산
행렬 계산은 앞서 말했듯이 한 번에 곱하여 하나의 행렬로 만들어 변환이 가능하다. 그러나 만약 위의 순서가 아닌 이동 변환을 먼저 하고 회전 변환이나 스케일 변환을 하게 된다면 기준점이 달라 물체의 이상한 부분이 커지거나 물체가 자전이 아닌 원점을 기준으로 공전을 하게 될 것이다. 따라서 제약이 가장 없는 이동 계산을 마지막으로 하고 가장 제약이 많이 따르는 스케일을 맨 처음 계산해 주는 것이다.

회전(Rotation)


엄지를 y축에 놓으면 감기는 부분이 +방향으로 다음과 같이 오른손 좌표계에서는 반시계 방향이 +방향임을 알 수 있다.


오일러 변환


회전을 표현할 때, 행렬을 보고 바로 어떠한 회전을 하였는지 알기는 사실상 어렵다. 따라서 사람이 편하기 위해 x축, y축, z축으로 몇도 회전 하였는지를 순서대로 차례로 표현하는 것이 오일러 변환이다. 여기서 축을 중심으로 회전하는 각도가 오일러각이라고 부른다.
대부분의 게임엔진도 사람이 이해하기 쉽게 오일러각도로 회전각을 보여주고 표현하도록 사용한다.


법선벡터 변환


모든 폴리곤들은 법선이라는(면이 어느 방향을 향하는지) 정보를 갖고 있다고 저번 시간에 배웠다. 이 법선도 모델이 회전을 한다면 당연히 변환이 일어나야 할 것이다. 그러나 만약 변환 행렬이 비균등 즉 x, y, z가 각각 다른 값을 가진 상태로 축소확대 변환을 시키면 법선벡터의 변환은 적용이 불가하다. 법선이 폴리곤과 수직이 아니기 때문에 더 이상 법선의 의미를 가질 수 없게 된다.
그러나 변환 행렬의 역행렬의 전치행렬을 적용하여 변환을 한다면 변환된 벡터는 항상 폴리곤에 수직이 되고 결국 법선을 의미하게 된다. 비균등 축소 확대이더라도 가능하다!

위 그림은 비균등 스케일링 변환 행렬인 경우에도 법선의 의미를 갖는다는 것을 수학적으로 보여준 것이다.

혼틈 선형대수학에서 생각해보면
두 벡터의 내적의 결과가 0이면 -> 두 벡터는 수직
|A||B|cosθ의 내적 연산에서 θ의 값이 90이 되면 내적의 연산 결과는 0이 된다. 그런데 θ는 두 벡터가 이루는 각도를 의미하기 때문에 두 벡터가 수직이라면 내적의 결과는 0이 되는 것이다.

그림에서 변환된 벡터에 변환 행렬의 역행렬의 전치 행렬의 내적 계산이 0이 됨을 보여준다.


카메라 변환(View)

변환 파이프라인에서 두 번째에 해당하는 뷰 변환이다. 처음 모델 좌표계로 주어진 모델의 정점을 월드 변환을 하면 모든 물체의 좌표는 전부 월드 좌표로 표현이 되고, 이 월드 좌표로 표현된 3D 게임 세상의 모델들을 카메라를 기준으로 다시 변환을 해야한다.

위 그림과 같이 카메라는 특정 파라미터를 갖는다.
EYE : 카메라의 위치
AT : 카메라가 바라보는 기준점
UP : 카메라 상단을 가리키는 방향을 대략적 묘사한 벡터(보통 월드의 y축)

따라서 다음과 같은 파라미터를 이용해 AT벡터에서 EYE벡터를 빼면 카메라의 로컬 Z축을 얻을 수 있고, 이 Z축과 대략적인 UP벡터를 외적을 하면 로컬 X축을 얻을 수 있다. 다시 X축과 카메라가 바라보는 LOOK벡터를 외적을 하면 UP벡터를 얻을 수 있다.

카메라의 EYE를 원점으로 한 상태에서 u, v, n 세개의 기저를 갖고 카메라 좌표계로 다시 표현할 수 있다. 이것이 카메라 변환!

카메라 변환의 순서이다.
쉽게 말해 그냥 카메라의 위치를 원점으로 가져다 놓고 모든 객체에도 똑같이 적용하면 끝!
위 그림에서 카메라의 위치에 (-4, 0, -2)를 카메라에 적용하면 카메라는 원점으로 이동할 것이다. 이 변환 행렬을 모든 객체에 적용하면 똑같이 이동할 것이다.
그렇게 되면 카메라는 (0, 0, 0)이 될 것이고 (8, 0, 3)의 객체는 (4, 0, 1)이 될 것이다.
이 후, 카메라의 z축을 월드 좌표계의 z축과 일치시켜야 한다.
쉽게 카메라를 90도로 이동 시키고 물체도 같은 변환을 적용한다.
이렇게 되면 모든 객체는 카메라를 중심으로 한 카메라 변환 성공!

여기서 눈치가 빠른 사람들은 깨달았을 것이다.
바로 카메라의 변환의 역변환을 모든 객체에 적용해주면 된다.

이렇게 월드 공간의 물체들을 카메라 공간으로 재정의하면 z축의 음의 방향을 가진 물체들은 모두 렌더링에서 빼는 경우와 같이 렌더링 알고리즘 적용이 쉬워 진다.

이 카메라 변환을 뷰 변환이라고도 한다.


내적

다음 그림과 같이 두 벡터의 내적을 나타낼 수 있고, 두 벡터의 크기에 각도를 곱해줘 나타낼 수 있다.
따라서 만약 두 각이 직각을 이루면 세타 값이 90이기 때문에 내적이 0이 된다.

  • 두 벡터의 내적이 0이 되면 수직이다.

그리고 두 벡터가 이루는 각이 예각이라면 cos의 값은 0~90에서 양수이다.

  • 두 벡터가 이루는 각이 예각이면 내적은 0보다 크다.
  • 두 벡터의 이루는 각이 둔각이면 내적은 0보다 작다.
  • 만약 a가 단위 벡터일 때 두 a벡터의 내적은 1이 될 것이다. (cos0 = 1 이기 떄문)

직교 정규기저


서로 수직인 단위 벡터들의 집합을 직교 정규 기저라 한다.

따라서 카메라 공간에서는 항상 직교 정규 기저 u, v, n 을 가진다.
그러므로 카메라의 서로 내적이 0이 되는 성질과 자기 자신을 내적하면 1이 되는 성질을 유지하도록 카메라를 회전하고 이동하며 변환을 처리를 해야할 것이다.


2D 공간이전


다음과 같이 2D의 월드 공간 좌표 p(1, 1)이 주어졌을 때, 카메라 공간 좌표로 이동시켜보자.
우선 카메라의 위치 EYE가 2, 2에 위치하고 있으므로 T의 변환을 시켜 원점으로 이동시켜준다.
그 다음 R을 통해 카메라를 월드 공간과 동일시키고, 이 T와 S를 p에 변환시켜주면 된다.

그렇다면 회전 변환 R을 어떻게 얻을 수 있을까?
직교행렬에서 역행렬은 그 행렬의 전치행렬과 같다고 선형대수시간에 배웠다.
따라서 카메라 공간 기저 벡터를 차례로 행에 배치하는 것이다.

그렇게 되면 다음과 같이 역행렬을 얻을 수 있고, 이를 각각에 변환을 시켜주면 놀랍게도 모든 좌표를 카메라 기준으로 옮길 수 있다.
따라서 p의 위치 또한 변환을 통해 얻을 수 있다.


3D 공간이전




위 그림과 같이 RT변환을 수행하였다면, (RT)^-1을 통해 T^-1 R^-1을 구할 수 있다. 따라서 이동 변환의 역행렬은 이동 변환에 각각의 요소에 마이너스를 해줌으로써 역행렬을 구할 수 있고, 다음으로 회전 변환에서 역행렬은 앞서 설명했다시피 행과 열을 바꿔 전치행렬을 만들어서 곱해줌으로써 최종적으로 위 그림과 같은 카메라 변환 행렬을 얻을 수 있다.

카메라 변환 행렬에서 잊지 말아야 하는 것이 있다. 우리가 이제까지 해준 카메라 변환 행렬은 카메라를 이동 시키기 위한, 즉 카메라를 게임 세상에 가져다 놓기 위하여 위치와 방향을 표현하기 위한 행렬이 아니라, 카메라를 이동해준 역행렬을 구함으로써 카메라 기준으로 모든 객체를 변환 하는 것이다.


카메라 절두체 : 뷰 프러스텀

카메라 공간 기저를 (u, v, n)이라고 하는 대신 (x, y, z)라고 하자
카메라 외부의 파라미터는 EYE, AT, UP일 것이다.
그렇다면 카메라 내부의 파라미터는 어떻게 될까
카메라의 영역을 의미하는 뷰 프러스텀(절두체)의 파라미터는 fovy, aspect, n, f가 존재한다.

  • fovy (field of view Y) : 수직 시야각
  • aspect : 종횡비
  • n : 근평면 거리
  • f : 원평면 거리

카메라 내부의 파라미터는 다음과 같이 이뤄져 있다.
이렇게 간단하게 카메라 절두체를 알아보았다.
그렇다면 만약 카메라 절두체의 바깥부분은 어떻게 될까
이는 뷰 프러스텀 컬링으로 잘라내야 한다.

  • 뷰 프러스텀 컬링 : 폴리곤 메쉬를 감싸는 직육면체 혹은 바운딩 볼륨을 미리 계산하고 CPU 프로그램에서 바운딩 볼륨이 뷰 프러스텀 바깥에 있는지 테스트해서, 그렇다면 폴리곤 메쉬는 렌더링 파이프라인에서 제외하는 것을 말한다. cpu에서 일어난다.
  • 그런데 컬링은 겹쳐지는 절두체와 겹쳐지는 폴리곤들의 리스트를 따로 구하지 않는다. 시간이 오래걸리기 때문에 따라서 완전히 포함되거나 겹쳐지는 오브젝트에 대해서만 렌더링을 수행을 하고, 원근 투영과 원근 투영 나누기를 하면 모든 절두체 공간이 NDC로 바뀔 수 있다. 그렇게 되면 NDC에서 안에 들어오는 점들을 찾기가 쉬워진다. 따라서 카메라에 보일 수 있는 오브젝트를 찾고 그 오브젝트에 대해서만 렌더링을 수행하는 것이 절두체 컬링이다.
  • 컬링과 클리핑의 차이가 헷갈릴 수 있는데, 컬링은 메쉬 자체를 제외시키는 것이고, 클리핑은 컬링에서 1차적으로 걸러지고 난 후 메쉬에 대해 수행한다.
    클리핑은 주로 메쉬의 일부분인 폴리곤을 잘라내는 작업을 한다. 그리고 컬링은 해당 메쉬가 시야를 완전히 벗어나는지만 검사한다.
    따라서 클리핑은 추가로 어느 영역이 벗어나는지를 검사해야 하기 때문에 컬링에 비해 더 많은 오버헤드가 필요하다.
    컬링은 주로 정적인 물체, 클리핑은 동적인 물체에 적용한다.

투영 변환(Projection)

뷰 프러스텀에서 폴리곤을 자르는 것은 쉽지 않다.
따라서 뷰 프러스텀을 클립 공간(클리핑을 위한 공간 2x2x1의 직육면체)으로 변환하고 폴리곤도 변환하는 것이 바로 투영 변환이다.
이렇게 변환한 클립 공간의 폴리곤의 클리핑은 쉽다.

뷰 프러스텀은 카메라(EYE : 투영 중심(COP))로 수렴하는 투영선의 집합이라고 할 수 있다.
투영선에 위치한 모든 3D점은 투영 평면의 한 점으로 맺히게 된다.

  • 원근 투영 : 멀리 있는 물체는 작게 보이는 투영으로 프러스텀은 직육면체로 바뀌고 COP는 무한히 멀어지며 투영선은 평평해지고 단일한 투영 변환을 가진다.
  • 직교 투영 : 단일한 투영 방향을 가지는 투영이다.

투영 변환 행렬

그렇다면 투영 변환 행렬은 어떻게 될까

투영 변환 행렬은 다음과 같다. 이러한 투영 행렬을 통해 클립 공간으로 이동한 메쉬들은 레스터화 단계로 넘어간다.
레스터 라이저는 모든 입력이 왼손 좌표계에 정의된 공간이라는 가정하에 작업을 수행한다.
따라서 현재 오른손 좌표계였던 공간을 왼손 좌표계로 바꿔줘야 한다.
이를 위해선 간단히 Z축에 좌표의 부호만 변경해주면 된다.

따라서 다음과 같이 3행의 좌표의 부호를 바꿔준다.
정점 처리와 달리 래스터화 단계는 하드웨어에서 처리된다.

투영 변환 후 카메라 공간은 오른손 좌표계에서 왼손 좌표계인 클립 공간으로 변환된다.
다음은 투영 변환 행렬을 생성하는 함수이다.


원근 투영(perspective projection) 변환 행렬



멀고 가까움을 느낄 수 있도록 그림을 그리는 원근 투영 변환
따라서 멀리 있는 오브젝트는 x와 y를 가까이 있는 오브젝트보다 더 많이 줄여야 한다.
예를 들어 1차로로 쭉 이어진 길이 있다 가정해보자

다음과 같이 사진을 보면 거리가 멀어질 수록 소실점에 수렴하고 훨씬 줄어든 것을 볼 수 있다.
따라서 (x, y, z)에서 x, y를 z로 나누면 된다.
따라서 z값이 큰 가장 멀리 있는 점들은 점점 거리가 줄며 결국 만나게 된다.
이러한 점들을 venishing 포인트라 하며 이런 투영이 바로 원근 투영이다.


fovy에 따른 변화

fovy는 수직 시야각이다. 따라서 fovy가 커지면 시야각이 커지고 결국 오브젝트의 크기는 줄어든다. 그렇게 되면 화면 전체를 차지하는 오브젝트의 크기가 줄어드는 것이고 결국 속도가 느려 보인다. 거기다가 그려야 하는 오브젝트의 개수가 늘어나며 결국 프레임 레이트가 줄어들게 된다.
요약하자면

  • fovy 증가 | 속도감 감소 | 시야각 증가 | 오브젝트 크기 감소 | 그려야 하는 오브젝트 개수 증가 | 프레임 레이트 감소
  • fovy 감소 | 속도감 증가 | 시야각 감소 | 오브젝트 크기 증가 | 그려야 하는 오브젝트 개수 감소 | 프레임 레이트 증가

그렇다면 스피드를 즐길 수 있는 레이싱 게임은 어떤 fovy를 설정해야 좋을까?
당연히 fovy가 작은 것을 선택하면 좋을 것이다.
속도감을 즐길 수 있기 때문이다.
이렇게 fovy를 줄이는 것이 프레임 레이트를 올리는 방법이다.

프레임 레이트를 올리는 또 다른 방법은 원평면까지의 거리를 줄이는 것이다.
원평면까지의 거리를 늘리게 되면 결국 z축에서 투영 면까지 거리가 늘어나게 되고 카메라에 보이는 오브젝트가 늘어날 것이다.
따라서 fovy를 줄이고 원평면 거리를 줄이면 프레임 레이트가 올라가게 된다.

또한 멀리 있는 것들은 잘 안보이거나 작고, 가려지기 때문에 대충 그린다.


투영 변환 행렬을 파헤쳐보자

  • (1)
    이제부터 투영 변환 행렬이 어떻게 저런 식이 나오는지 파헤쳐 보도록 하자

    우선 projection plane에 투영된 y'를 범위[-1, 1]을 이용해서 계산해보자

    그렇다면 현재 프로젝션 플랜의 y 값이 1이기 때문에 tan(fovy / 2)가 1 / z'가 된다.
    따라서 cot인 역수로 바꿀 수 있고 각각의 비율을 맞춰 계산하면 y'를 얻을 수 있다.

  • (2)
    x' 또한 y'를 구한것 처럼 구할 수 있다.

    다음과 같은 방법으로 종횡비를 구할 수 있으며, 종횡비를 통해 x'를 구할 수 있다.

  • (3)
    드디어 x'와 y'를 구했다.

    이처럼 y'값만 구해도 x'를 구할 수 있다.
    그리고 공통된 부분 D를 묶어

    다음과 같이 동차 좌표계로 표현할 수 있다.

    결국 다음과 같이 투영 행렬을 구할 수 있다.
    그런데 여기서 z는 x, y에 독립적이기 때문에 m1, m2는 0이다.


    여기서 -f와 -n은 -1과 0으로 변환이 되며 클립 공간이 된다.
    따라서 두 식을 적용하여

    m3와 m4를 얻을 수 있다.
    결국 이 모든 것을 대입하여 계산하면

    다음과 같은 아름다운 식이 나오는 것이다.

이제 모든 투영은 끝났다. 그저 z만 없애면 3차원 좌표계가 2차원 좌표계로 뿅~! 하게 된다.

이렇게 모든 변환이 끝났다.
어떻게 보면 굉장히 긴 것 같지만 내용은 사실상 많이 어렵진 않다.
이렇게 2차원의 좌표계로 옮기게 되면 픽셀들의 정보를 얻게 되고, 각 픽셀들에 대해 색깔을 결정을 해서 렌더링을 할 수 있게 된다.

profile
코딩 초보 승호입니다.

0개의 댓글