랜더링 파이프라인

Unity3D 2020. 12. 21. 15:40
반응형

rapapa.net/?p=3531

 

렌더링 파이프라인의 좌표 공간들 – Rapapa Dev Story

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

rapapa.net

버텍스 데이터가 최종 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들을 살펴보자. 

 

즉, 유니티에서만 보더라도, 손쉽게 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

반응형
: