본문 바로가기

유니티 쉐이더 스타트업

[ 유니티 쉐이더 스타트업 ] 03 - 1 . 렌더링 파이프 라인 - 정점 조립과 버텍스 셰이더

[ 렌더링 파이프 라인]

[ 렌더링 파이프 라인이란 ]

간단히 말해 GPU를 사용하여 리소스를 2D이미지로 렌더링 하는 과정이다 .

즉, 모니터 (2D)에 보여주는 과정 .


 

[ 렌더링 파이프 라인의 과정 ]

렌더링 파이프 라인

렌더링 파이프 라인의 과정이다 이중 , 정점 조립버텍스 셰이더를 살펴본다 .

 


 

[ 렌더링 파이프 라인 : 정점 조립 ]

[ 정점조립 ]

정점 버퍼의 요소들을 정점 구조체로 조립한다.

즉 ,string 형태의 데이터를 정점 구조체 단위로 조립하는 것

이때 ,렌더링 파이프라인 상태 내부의 정점 서술자(정점 명세 오브젝트)가 정점 스트림의 데이터를

어떤 방식으로 어느 범위까지 각각의 정점 구조체로 조립해야하는지 묘사한다 . 

이 결과  Stream 형식의 데이터 버퍼가 각각에 대한 정점 구조채로 사용하기 좋게 조립된다 .

각 정점의 구성을 명시적으로 선언 가능하고 , 정점 구조체의 이름도 정의 가능하다 .

이때 ,Vertex Input이라는 이름은 쉐이더에게 넘겨줄 정점 데이터의 타입명을 정한것 .

 

=>이러한 정점 조립 과정은 유니티가 알아서 처리하며 , 

직접 해야하는 일은 사용할 정점의 구성을 구조체로 선언하는 것이다 .

 

정점 조립을 거치게 되면 삼각형에 대한 3개의 정점으로 구성되고 , 버텍스 쉐이더에서 병렬로 처리하여 

또다른 형태의 정점으로 변환될 것이다 .

 


 

[ 렌더링 파이프 라인 : 버텍스 셰이더]

[ 버텍스 셰이더 ]

정점을 입력받아 다른 형태의 정점으로 변환한다 .

주요 역할은 3D 공간 상의 정점의 위치를 클립 공간 (카메라 화면에서 본)으로 옮기는 것.

 

이는 배가 움직이는게 아닌 , 세상이 배의 반대방향으로 움직인다 묘사 할 수 있다 .


 

[ 변환 행렬 ]

버텍스 셰이더는 정점의 위치를 옮기기 위해 변환 행렬을 사용한다 .

각 정점을 변환 행렬을 거치게 하여 위치를 변환해준다 .

변환 행렬은 내부적으로 3개의 변환행렬의 연속이다

(연산상에는 하나의 행렬의 곱하기지만 위의 3개의 행렬의 순서적용이라고 봐도 무방하다)


 

[ 변환행렬 00 : 변환전 정점상태 ]

  • 스스로가 세상의 중심
  • 모델의 피벗 포인트를 원점으로 가진다
  • 모든 정점은 해당 피벗 포인트로부터 얼마나 떨어져있냐로 결정된다

즉 , 오브젝트 공간에서 오브젝트는 0,0,0 지점에 있다 .


 

 

[ 변환행렬 01 : 모델 행렬]

오브젝트 공간에 존재하던 정점에 모델행렬을 곱하게 되면 월드공간 기준으로 배치된 정점으로 변환된다 .

즉 , 모델행렬은 오브젝트의 정점들을 월드상의 위치로 옮기는 역할을 하게 되는 것이다 .

즉, 세상의 중심이 모델의 위치 반대로 밀려나게 된다 ( 월드속의 자신의 위치로 원점에서 밀려나는 것과 같은 효과 )


 

 

[ 변환행렬 02 : 뷰행렬]

월드 상의 정점들을 카메라에 상대적 위치로 옮김 (카메라가 원점에 있다 가정하는 것)

 

카메라가 원점에 있다 가정한 공간을 카메라 공간이라고 한다

카메라 공간은 왜 필요할까?

  • 같은 위치에 있는 물건도 카메라의 위치에 따라 다르게 보인다
  • 매번 카메라의 위치, 회전의 고려보다 카메라는 원점에 두고 오브젝트를 상대적으로 배치하는게 간결하기 때문

뷰 행렬을 월드 공간상의 정점에 곱해주면 좌표계의 중심은 카메라의 위치로 이동한다

변환 이전의 월드상의 원점에서 카메라까지의 거리와 방향의 반대로 모든 정점이 밀려나는 효과를 내게 됨

결과적으로 카메라의 위치를 기준으로 모든게 재편성되고 , 이제 정점들은 카메라 공간으로 투영된 정점이다 .

 

[ 변환행렬 03 : 투영 행렬]

투영 행렬은 카메라 위치를 기준의 정점을 카메라 시야 기준 (화면)의 정점으로 바꾸어준다

  • 카메라 좌표계의 정점을 카메라의 시야(뷰포)를 기준으로 한 정점으로 옮김
  • 투영행렬은 카메라 좌표계의 정점들을 클립 공간을 옮김
  • 깊이와 원근감을 표현 할 수 있게 함

클립 공간은 카메라의 뷰포트를 기준으로 생성된 공간 .

카메라가 보는 영역(뷰포트)을 직육면체(API에 따라 큐브)로 압축한 공간이다 .

x , y 의 범위는 (-1 ~ 1) / z의 범위는 (0 ~ 1) 이다 .

  • 카메라 공간 : 단순히 카메라의 위치를 원점으로 - 시야와 원근감 없음
  • 클립 공간 : 카메라의 시점 반영 -> 시야와 원근감 존재 (볼 수 없는 부분을 잘라냈기에 클립 공간이라 불린다)

이후 , 클립 공간 외부의 폴리곤은 NDC로 변환되는 과정에서 잘려나간다 . (클리핑)

 

NDC (Normalized Device Coordinates) 즉 , 정규화된 기기 좌표계는 카메라가 보는 공간인 클립공간을

클리핑을 시도한 후 3차원의 직육면체로 변환한 공간이다 .

 

공간의 모든 x,y,z의 범위가 (-1~1  또는 0~1)로 지정된 영역을 가지기에 정규화된 기기 좌표계로 부른다 .

 

다음의 절차를 통해 생성이 된다

  • 클립 공간 외부의 좌표를 잘라낸다
  • 동차 좌표계 (4차원)을 w 나누기를 실행하여 3차원으로 변환한다 .

클립 공간과 NDC는 종종 하나로 묶어 설명한다 .

  • 사실상 서로 같은 모습 : 뷰포트를 직육면체로 쪼그라뜨린 공간
  • 클립공간은 행렬계산 편의를 위해 4차원 (동차 좌표계 : 계산은 4차원에서 이루어지지만 3차원과 동일함)에 존재한다 즉, 오브젝트 , 월드 , 카메라 ,클립 공간까지는 계산의 편의를 위해 3차원의 공간을 4차원의 공간을 빌려 계
  • NDC는 클립핑 실행후 원래 의도된 3차원 공간으로 변환된 것이다 .

투영 행렬이 하는 일은 뷰포트를 직육면체의 클립공간으로 바꾸어준다 .

 이 과정에서 카메라 렌더 영역과 원근감이 생긴다 .

뷰포트의 영역을 투영행렬을 통해 직육면체로 정규화가 가능하다. 즉, 모든 영역이 아래의 클립공간으로 찌부러트려 진다

 

변형 전,후 뷰포트 외부에 있다면 잘려나가게 된다 .

또한 , 원근감은 다음의 이유로 생성되게 된다 .

 

[ 정리 ]

버텍스 쉐이더는 행렬 변환을 통해 3D공간의 정점을 클립공간의 정점으로 옮긴다 .

다음의 삼각형으로 예를 들어보자 .

삼각형의 위치가 -50,0,200 이었으니 다음과 같은 월드공간에 놓인다

카메라의 위치에 따라 다음의 위치로 재편성 된다 .

투영행렬에 대한 변환의 적용으로 500,500,500의 뷰포트가 2,2,1의 직육면체로 변화하게 되면

-250의 정점이 -1로 옮겨지는 효과가 나온다 .

결국 ,카메라가 그릴 화면의 최좌측을 -1 최우측을 +1 세로 역시 같고 , 카메라의 깊이를 0에서1로 봤을때 기준으로 모든 좌표는 재편성된다 .

결국 이러한 모습을 갖추게 되는 것 .

 

출처

https://www.youtube.com/watch?v=BMT0xCxP6w8

https://www.youtube.com/watch?v=aYTJY_DneSY&t=20s

https://rito15.github.io/posts/rendering-pipeline/

유니티 쉐이더 스타트업

https://www.youtube.com/watch?v=aYTJY_DneSY