2022. 7. 10. 19:05ㆍPublic/Shader
좌표 공간에는 여섯 가지 좌표 공간을 다룰 것이다.
객체공간(Object Space),
월드 공간(World Space),
카메라 공간(Camera Space),
절단 공간(Clip Space),
정규 디바이스 좌표(Normalized Device Coordinates),
스크린 공간(Screen Space)
이 여섯 가지는 부분의 그래픽스 파이프라인 안에서 사용하는 순서다. 정점 셰이더에 전달하는 데이터는 객체 공간 기준이다. 데이터 중 일부는 월드 공간으로 변환돼야 한다.(라이팅 계산에서 사용된다.)
또 다른 데이터들은 카메라 공간으로 변환될 것이고 결국에는 절단 공간 등으로 변환될 것이다.(정점 위치)
객체 공간(Object Space)
객체 공간은 3D 좌표체계로 원점은 주로 입력 조립 단계에서 렌더링 파이프라인으로 보낼 메시의 아래쪽이나 중앙으로 잡혀 있다.
원점은 주로 메시를 제작하는 데 사용한 3D 모델링 소프트웨어의 중심점(pivot point)에 잡혀 있을 확률이 높다.
이 객체 공간은 로컬 공간(Local Space),모델 공간(Model Space)이라고도 부른다.
appdata에 정점 위치를 저장해 정점 셰이더에 전달할 때 정점의 위치는 객체 공간 기준이다.
월드 공간
월드 공간에서 참조의 기준은 하나의 메시가 아닌 전체 씬이다.
유니티에서는 이것이 씬이 존재하는 공간이며 게임 오브젝트에서 사용하는 좌표는 공간 좌표로 변환해야 한다.
각기 다른 좌표 공간을 변환하는 데에는 주로 행렬 곱을 사용한다. 행렬의 편리한 기능 중 하나는 행렬을 구성할 수 있다는 점이다. 따라서 어떤 행렬은 객체 공간에서 절단 공간으로 변환할 수 있다.
유니티는 어떤 값의 타입을 변환하는 데 자주 사용하는 내장 함수들을 다수 포함하고 있다. 이러한 값의 타입으로는 위치, 노멀, 빛의 방향 등이 있다. 다음은 월드 공간에서 특정한 값을 얻을 수 있는 함수들이다.
카메라 공간
시야 공간(Eye Space),뷰 공간(View Space)라고도 한다.
이 좌표 공간은 월드 공간 좌표 체계와 동일한 씬을 담는다. 하지만 렌더링의 시발점인 카메라의 시점으로 씬을 담는다.
카메라 공간이 필요한 이유는 절대 공간을 출력하는 데 필요한 단계이기 때문이다.
단 , 이 단게의 대부분은 표준 셰이더 하부구조(infrastructure)에서 담당한다. 카메라 공간에 사용하는 몇 가지 내장 행렬들이 존재한다.
unity_WorldToCamera : 월드 공간에서 카메라 공간으로 변환한다.
unity_CameraToWorld : 위 행렬의 역행렬이다. 카메라 공간에서 월드 공간으로 변환한다.
또한 하나의 내장함수가 있다.
float4 UnityViewToClipPos(in float3 pos) : 뷰 공간에서 절단 공간으로 위치를 변환한다.
절단 공간
렌더링 파이프라인의 정점 후처리 단계에는 절단(Clipping)을 포함한다. 절단은 절단 공간의 경계에 조금이라도 속해 있지 않는 기본 요소들을 제거한다. 절단 공간의 좌표 범위는 -1에서부터 1까지다.
여기에서 직관적이지 않는것이 하나 존재한다.
현재까지의 좌표공간은 3개의 좌표축이 있을것이라고 생각할것이다. (x.y.z) 하지만 OpenGL, 다른 API의 3D 공간에서는 4개의 좌표축을 사용한다 (x.y.z.w).
w 좌표가 존재하는 이유는 3D 렌더링에 카테시안 공간을 그대로 사용하면 두 평행선은 서로 만날 수 없기 때문에 원근법을 표현하기가 불가능하다.
이 문제를 해결하기 위해서 좌표를 하나 더 추가한 것이다. 이것을 동차 좌표(homogeneous coordinates)라고 한다.
따라서 객체, 월드, 뷰, 절단 공간은 4차원 좌표를 사용해 표현한다.
단, 절단 공간을 제외하고 w는 1이다.
뷰 공간에서 절단 공간으로 벼노한하는 데 사용하는 행렬에 의해 w값은 1이 아닌 다른 수로 바뀐다.
이 행렬을 OpenGL에서는 투영 행렬(projection matrix)이라고 부른다. 그리고는 w 값을 통해 정점을 잘라낼지를 결정한다. 투영 행렬을 설정하기 위해 시야부피(절경frustum이라고도 한다)와 관련된 정보가 필요하다.
절단 공간에 활용하는 내장 행렬은 존재하지 않는다. 다만 몇 가지 내장 함수들이 존재한다.
float4 UnityWorldToClipPos(in float3 pos) : 위치를 우러드 공간에서 절단 공간으로 변환
float4 UnityViewToClipPos(in float3 pos) : 위치를 뷰 공간에서 절단 공간으로 변환
float4 UnityObjectToClipPos(in float3 pos) : 정점 위치를 객체 공간에서 절단 공간으로 변환
정규 기기 좌표
정규 기기 좌표(Normalized Device Coordinates, NDC)이다.
이것은 2D 공간이고 특정 스크린이나 이미지 해상도에 의존적이지 않다. NDC 기준 좌표는 절단 좌표를 w로 나눠서 얻는다.
이 과정을 원근 분활(perspective division)이라고 부른다.
OpenGL에서의 NDC좌표 역시 -1 ~ 1 까지의 범위를 갖는다.
NDC는 세 가지 숫자를 사용한다. Z값은 동차 좌표를 의미한 것이 아닌 z버퍼(깊이 버퍼)를 위한 것이다.
[z버퍼 설명 사진]
화면 공간
화면 버퍼가 될 수도 있고 분할 렌더 타깃이 될 수도 있으며 하나의 이미지도 될 수 있다. 이것은 NDC를 뷰포트(viewport) 해상도로 확대 축소하고 변환해서 얻을 수 있다. 마침내 정점의 이러한 좌표가 레스터라이저로 전달된다. 그리고 레스터라이저는 이것을 가지고 프레그먼트를 생성한다.
참고 서적: http://www.yes24.com/Product/Goods/72174329