DirectX로 엔진 만들기 #1

 

파이프라인? 

여러  명령어가 중첩되어서 프로그램이나 하나의 작업을 실행하게 도와주는 과정(연산들의 집합).

예를 들어, 3차원에서 2차원으로 변환하는 데에는 무수히 많은 단계를 거친다. 이처럼 복잡한 단계를 거친 변환에서 거치는 단계들을 의미한다.

 

한 사이클 안에 변환 과정이 전부 들어가야 해서 한 사이클이 복잡해지거나 사용자 입장에서 어려워질 수 있는 단점이 존재한다. 

 

렌더링파이프라인 (레스터라이제이션 - Rasterization)

3차원을 2차원으로 변환해주는 일. 아래 그림과 같이 다음의 단계를 거친다.

 

Input Assembler (입력 조립 단계)

모델은 점(Vertex)으로 이뤄져 있다. 우리는 이를 폴리곤(점들의 집합)이라 한다.

주로 게임에서는 삼각형을 가지고 3D 폴리곤을 정의하는데, 이 때 정점데이터들을 운반하는 자료 구조를 Vertex Buffer(정점 버퍼)라고 한다.

 

정점 버퍼와 같이 등장하는 용어로 Index buffer(인덱스 버퍼)라는 것이 존재한다. 이는 정점들의 인덱스를 저장하고 있는 버퍼라고 할 수 있는데, 예를 들어 사각형을 삼각형 기반으로 그리기 위해서는 (2 * 3 = 6) 여섯 개의 정점이 필요하다.

 

하지만 여기서 사각형을 구성하는 정점을 4개만 두고, 4개를 한 붓 그리기와 같이 중복해서 그려주는 방식을 인덱스 버퍼의 기능이라고 생각할 수 있다. (물론 없어도 상관 없다.)

 

추가적으로 인덱스 버퍼를 사용하는데, 그것도 '결국 메모리를 사용하니 동일하지 않나?' 라고 생각할 수 있다.

정점은 위치 데이터 말고도 색깔, 법선, 텍스처좌표(UV), 애니메이션에 필요한 정보 등을 여러가지 프로그래머가 원하는 데이터를 추가하여 사용하기에 단순히 정수만 저장하는 인덱스버퍼가 훨씬 메모리적으로 효율적이다.

 

다시 정점 버퍼로 돌아와서, 정점버퍼는 그저 정점들의 연속적인 메모리 구조에 불과하기 때문에 실제로 GPU에서는 이러한 정점들을 이용하여 어떤 도형을 만들어야 하는지 정보가 필요하다. 이 때, 해당 도형 정보를 Primitive Topology(기본 토폴로지) 라고 한다.

 

결론적으로 Input Assembler는 이러한 정점들의 데이터를 읽고, 삼각형과 같은 도형으로 조립하는 단계의 일을 한다고 생각하면 된다!!!

 

Vertex Shader (버텍스 쉐이더)

Input Assembler 에서 받은 정점 정보들로 도형은 생성이 되었지만, 로컬 좌표계에 있기 때문에 해당 데이터들을 화면에 그대로 출력해버리면 화면 중심부에 모든 도형이 그대로 출력된다. 따라서 공간 좌표계로 변환할 필요가 있다. Local Space에서 World Space로 변환하고, 실제 플레이어가 바라보는 카메라가 중심이 되는 공간인 View Space 변환을 실시한다. 그리고 마지막으로 Projection 변환을 거쳐 최종적으로 정의된 Clip Space라는 공간으로 변환하게 된다.

 

월드공간 변환

Local Space라고 불리는 오브젝트 공간은 3차원 세상에서 효현될 각각의 개인 공간에 정의된 영역이다.

 

카메라 공간 변환

월드 변환이 완료되어 모든 물체가 한 공간(World Space)에 모아지면, 이제 우리가 원하는 시점에서 물체를 관찰할 수 있게 해줘야 한다. 이 때 관찰자로서 가상의 카메라가 요구되고 이 카메라 시점의 공간을 View Space라고 한다.

 

월드 공간의 모든 물체를 카메라 공간으로 변환하게 된다면 효율적으로 여러가지 효과나 렌더링 등을 진행할 수 있다.

 

가상의 카메라는 컴퓨터의 성능 한계 때문에 실제 세상과는 다르게 시야가 제한될 수 있다. FOV(시야각), ASPECT(종횡비)에 의해 결정되는데, 이러한 가시영역을 View Volumn(뷰 볼륨)이라 한다. 이렇게 생성된 뷰 볼륨에 Near, Far 정보가 전달되어 두 물체의 영역을 다시 정의한다.

 

View Frustrum (뷰 절두체)

절두체 공간 밖에 있는 물체는 그리지 않는데, 우리가 살고 있는 3차원 세상은 모든 걸 보여준다. 이렇게 밖에 없는 이유는 계산 상의 효율성을 위해 어쩔 수 없이 도입된 개념이다. 만약 물체가 절두체의 경계를 걸치게 되면 바깥쪽 부분은 잘려서 버리게 된다. 이를 Clipping (클리핑) 이라 한다. 클리핑은 카메라 변환에서 이뤄지지 않고 후에 클립공간에서 레스터라이저로 넘겨질 때 수행된다.

 

투영 변환 (Projection Transformation)

View Space로 변환 시 카메라 공간으로 월드의 모든 물체를 재배치하고, 이제 카메라 시점에서 세상을 바라보게 된다. 우리가 카메라를 통해서 바라보는 가상의 공간은, 현실 세계처럼 3차원이지만 최적으로 우리가 바라봐야 할 공간은 모니터 세상인 2차원 공간의 세계가 되어야 한다. 그럼 3차원 공간을 어떻게 2차원으로 표현할 수 있을까?

 

3차원 세상을 2차원 평면에 표현하는 방법은 오래 전 화가들에 의해 개발되었다. (원근법)

 

투영 변환은 이러한 원근법을 구현하기 위해 카메라 공간에서 정의된 절두체를 3차원 클립공간으로 변환하는 것을 의미한다. 여기서 투영변환이라는 이름과는 다르게 3차원 공간의 물체를 2차원 평면으로 바꾸는 것이 아니라 3차원 물체로 변형됨에 주목해야 한다.

 

이러한 투영 변환을 거친 물체들을 관찰하면, 절두체 뒤쪽에 있던 영역의 폴리곤은 상대적으로 작아지는 것을 볼 수 있는데 우리가 원했던 원근법이 적용된 것이라고 볼 수 있다.

 

추가적으로 원근법을 3차원 공간에서 실현하기 위해 직육면체 볼륨으로 물체들을 변환시켰는데, 좀 더 간단한 공식으로 Clipping(클리핑) 작업을 할 수 있다는 장점도 있다.

 

 

 

 

 

 

 

 

 

참고) https://www.youtube.com/watch?v=Wry5ltdrDQI&embeds_referring_euri=https%3A%2F%2Fwww.inflearn.com%2F&source_ve_path=MjM4NTE

'WinAPI, DirectX' 카테고리의 다른 글

WinAPI로 엔진 만들기 #1  (0) 2024.09.12
DirectX로 엔진 만들기 #2  (0) 2024.09.12