Rapapa Dev Story

Game&Web Development And More…

렌더링 파이프라인의 좌표 공간들

렌더링시에 Object가 화면에 나오기까지의 좌표 공간들을 이해하는 것은 게임이나 Graphics 관련 개발에서 필수이다. 그 좌표계들을 나누는 방식과 이름 불리워지는 방식은 여러가지가 있지만 대게 아래와 같이 5개로 나눈다.

Model(Local) Space
World Space
View(Camera, Eye) Space
Clip Space
Screen Space

그림으로 표현하면 아래와 같다. 

버텍스 데이터가 최종 Pixel로 화면세 표현되기까지의 공간 변환들인데, 이 각각의 변환들은 Matrix 연산에 의해서 이뤄진다. 

Model(Local) Space 는 Object Pivot이 Local 좌표계 상에서 원점에 존재하는 공간이다. 3D 모델링 툴인 Max나, Maya, Blender에서 Fbx 포멧으로 Export하여 저장된채 게임에 쓰여지는 Vertex 공간이다. 동일한 모델링 모델링 fbx의 나무 의자가 12개 있다면 그 의자가 가지는 Model Space의 Vertex 데이터는 모두 동일하다. 

World Space는 Object를 공간 상에서 특정한 World로 이동 및 회전, Scale 된 좌표이다. 이는 Model Matrix로 변환이 이뤄진다. 

이는, 나무 의자들이 방안 곳곳에 놓여지게 되는 작업이다. 

View(Camera) Space는 World 상에서 놓여진 Object를 그것을 바라보는 카메라의 시점으로 옮긴 공간이다. 즉 실제 눈으로 보이는 것을 상대 좌표로 변환 시킨 공간이다. Position, Rotation, Scale이 적용되며, 이는 View Matrix의 곱하기 연산으로 이뤄진다. 

나무의자들이 곳곳에 놓여진 방에 물체를 바라보는 기준으로 카메라를 설치하는 작업 정도가 될 것이다. 

그런데, 우리 눈은 앞쪽에 있는 모든 물체를 볼 수 없듯이, 카메라 또한 앞쪽에 있다고해서 다 보여지는 것은 아니다. 

Clip Space는 카메라의 Frustum 공간 밖, 즉 보여지는 공간 밖에 위치해 있어서 보여지지 않는 오브젝트를 걸러낸다. 그리고, 카메라의 뷰에 따라서 Perspective View, 혹은 Orthogonal View를 적용한 상태로 만드는 변환 공간이다. 이 변환은 Projection Matrix 적용으로 이뤄진다. 

OpenGL에서는 GL_PROJECTION Matrix가 이 Projection Matrix인데, Perspective View를 정의하는 glFrustum()과 Ortho View를 만들어내는 glOrtho() 두개로 나뉜다. 

Clip Space에서 NDC(Normalized Device Coordinate) 공간을 따로 분리하기도 하는데, 이는 디바이스에서 사용하기 쉬운 Normalized 된 형태의 좌표계로 변환 시키는 연산이다. Vertex 값을 Homogeneous Coordinate의 w값으로 나눈다. (x, y, z, w) -> (x/w, y/w, z/w, 1). 이 연산은 최적화를 위해서 Cliping이 일어난 후에 발생한다.

플랫폼별로 Normalized된 값은 Y의 경우 -1.0 ~ 1.0으로 동일하고, Aspect Ratio에 의해서 Y 기준으로 X값도 유추할 수 있다. 그런데, Depth값 z의 경우 Direct3D, Metal 의 경우엔 0.0 ~ 1.0 값으로, OpenGL의 경우 -1.0 ~ 1.0의 값을 가진다. 유니티 쉐이더에서는 UNITY_NEAR_CLIP_VALUE 값을 사용하면 현재 플랫폼에 해당하는 값을 가져올 수 있다. 

유니티 Cg 쉐이더에서 Vertex program의 Output은 바로 이 Clip Space의 좌표이고 Vertex program의 연산 이후에 NDC 연산은 내부적으로 알아서 해준다. 

이 Clip Space는 의자가 놓인 방에 설치된 카메라의 Frustum 바깥쪽을 Cliping 시키고, 카메라의 Fov를 적용한 후에 Normalize 한 것 쯤 될 것이다. 

Screen Space는 Clip Space의 좌표들을 Screen 좌표계, 즉 화면에 보이는 공간으로 이동시키는 변환이다. -1 ~ 1.0 사이에 있었던 점들이 디바이스의 픽셀 화면 비율로 맵핑이 이뤄지는 것이다. Viewport Transformation 연산으로 이뤄진다. 

이 개념을 가지고, 유니티의 쉐이더를 만들때 사용되는 Built-in Matrix들을 살펴보자. 

Transformations

All these matrices are float4x4 type.



NameValue
UNITY_MATRIX_MVPCurrent model * view * projection matrix.
UNITY_MATRIX_MVCurrent model * view matrix.
UNITY_MATRIX_VCurrent view matrix.
UNITY_MATRIX_PCurrent projection matrix.
UNITY_MATRIX_VPCurrent view * projection matrix.
UNITY_MATRIX_T_MVTranspose of model * view matrix.
UNITY_MATRIX_IT_MVInverse transpose of model * view matrix.
unity_ObjectToWorldCurrent model matrix.
unity_WorldToObjectInverse of current world matrix.

UNITY_MATRIX_MVP는 Local Space의 Vertex를 Clip space로 옮겨주는 Matrix이다. 

이제 위의 공간에 대한 개념과 Built in Matrix를 가지고 공간과 공간 사이의 변환을 어떤 연산으로 할지 아래 표를 보면 유추가 가능하다.

즉, 유니티에서만 보더라도, 손쉽게 Built-in Matrix들을 이용해서 Vertex 데이터를 다양한 공간으로 옮길 수 있다.

DirectX나 OpenGL로 게임을 만들던 시대에서 유니티로 넘어오면서, Render Engine에 대한 깊은 이해의 필요성이 많이 사라졌던 것이 사실이었다. 특히 유니티의 BlackBox 같았던 내부 렌더러와 엔진 코드들은 아무도 갈 수 없던 금단의 영역이었다. 그러나, 최근 유니티가 SRP(Scriptable Render Pipeline)를 적극적으로 도입하고 엔진 내부 코드를 C#단으로 많이 올려 공개하기 시작했다. 자연히 그러한 방향으로 전진하고 있는 유니티 엔진을 잘 쓰기 위해서는 이런 렌더파이프라인의 공간 변환 개념들 또한 명확하게 이해할 필요성이 높아졌다.

reference:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
https://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter04.html
https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
https://answers.unity.com/questions/1443941/shaders-what-is-clip-space.html
https://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter04.html




답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

0
Would love your thoughts, please comment.x
()
x