본문 바로가기
Unity/ShaderGraph (대마왕님)

[Unity/ShaderGraph] 03-1. 렌더링 파이프라인 (Rendering Pipeline)

by 꿀팔자 2023. 4. 19.

* 이 포스팅은 책 '대마왕의 유니티 URP 셰이더 그래프 스타트업, 2023'을 학습하고 개인 학습용으로 정리한 내용입니다.

더 자세하고 다정한 설명을 원하시면 !꼭! 책을 보시길 바랍니다.

 

 

- 책에서 사용한 Unity 버전: 2021.3.5  
- 포스팅에서 사용한 Unity 버전: 2021.3.9  

- Render Pipeline: URP  
  Part 03.
  셰이더를 익히기 위한 기반 지식들
  1. 렌더링 파이프라인 (Rendering Pipeline : 렌더링의 순서)
      1) 오브젝트 데이터 받아오기
      2) 정점 셰이더 (Vertex Shader)
      3) 래스터라이저 (Rasterizer)
      4) 픽셀쉐이더 (Pixel Shader) / 프레그먼트 쉐이더 (Fragment Shader)

 

 

 


* +로 표시된 건 제가 추가한 부가 설명입니다.

 

 

 

 1. 렌더링 파이프라인 (Rendering Pipeline)  

- shader의 제작흐름
- 알면 여러 가지 발생할 수 있는 문제의 해결과 최적화 도움
- 제작한 3D 모델이 '면까지 생성된 모델링' 모습이 엔진으로 export 될 거라고 생각할 수 있지만, 
   엔진으로 넘어가는 건 vertex 안에 들어있는 데이터들 뿐임.

 

 

    [ 추가 노트 ] 
 


사진출처: https://graphicscompendium.com/intro/01-graphics-pipeline 

  + 이 그림을 보고 순서를 이해하면 편할 것 같습니다. 추가 노트는 더 깊은 내용을 다뤄서 나중에 읽어보면 좋습니다.



  - element array
    : 다각형(primitive)의 인덱스(index) 데이터를 저장하기 위한 버퍼
    : 이 데이터는 보통 삼각형(triangle)의 경우 3개의 인덱스로 이루어진 세트를 저장
    : 그래픽스 작업 중에는, 이러한 인덱스 데이터를 사용하여 꼭짓점 데이터를 결합하여 삼각형, 사각형 등의 다각형을 생성

  - vertex array
    : 3D 모델의 꼭짓점(vertex) 데이터를 저장하기 위한 버퍼

    : 이 데이터는 보통 좌표, 노멀(normal), 텍스처 좌표(uv) 등의 정보를 담고 있음.
    : 이렇게 저장된 꼭짓점 데이터는 GPU에서 그래픽스 렌더링 작업 중에 사용

  - element array / vertex array 차이?
    : 모두 그래픽스 렌더링을 위해 사용되지만, element array는 삼각형의 인덱스 데이터, vertex array는 꼭짓점 데이터 저장


  - triangle assembly
    : 3D 모델을 렌더링할 때, 그 모델의 각 삼각형을 GPU가 처리할 수 있는 형태로 변환하는 과정
    : 이 과정에서, 모델의 vertex와 index data를 이용하여 삼각형을 형성
    : 이렇게 생성된 삼각형들은 그래픽 파이프 라인의 다음 단계로 넘어가게 되어, 색상, 텍스처, 셰이더 등을 적용
    : Triangle assembly는 GPU에서 실행되므로, 이 과정은 매우 빠르고 효율적으로 처리


 

 

 


 

 

 

1) 오브젝트 데이터 받아오기

     - 그래픽 카드는 버텍스(vertex)로 이루어진 물체 데이터 값을 받아온다.
     - 아직 화면에는 아무것도 존재하지 않고, 그래픽 카드 내부 값으로만 존재하는 데이터뿐
     - vertex는 필요한 정보 가짐

       ex) 인덱스 넘버(index number), 포지션 (Position), 노멀(Normal), 컬러(Color), UV(Texcoord)

     - 그래픽 카드에서 이 정보를 가지고 (DirectX, OpenGL을 통해) 버텍스들이 이어진 삼각형 면을 생성하게 될 것
     - 오브젝트의 기본적인 형태가 갖추어졌고, 이 정보들을 버텍스 쉐이더로 넘길 준비 완료

     + 자세한 과정이 궁금하시면 위에 있는 [추가노트]를 참고하세요!

 

 

 

 


 

 

 

2) 정점 셰이더 (Vertex Shader)

    (1) 로컬 좌표계

        - 버텍스 위치 값은 현재 로컬(Local) 좌표계 상태
        - 로컬 좌표계=오브젝트 좌표계(유니티): 물체가 가지고 있는 '자기중심적인' 위치 값
        - 오프젝트별로 가지고 있는 본인의 피봇이 0, 0, 0 위치 값(중심값)인 상태
        - 여기서는 게임 안에 존재할 수 있는 다른 오브젝트의 위치는 전혀 고려되지 않는다.
        - 즉, 모든 오브젝트들은 자기가 세상의 중심인 상태

        - 모든 오브젝트들은 각각 자신이 세계 중심이며, 자신이 있는 곳이 원점(0,0,0)이라고 생각하고 있기 때문.

 

 

 

 

    (2) 월드(모델) 좌표계

        - 월드 변환 행렬(월드 좌표계)을 곱해줌으로써, 로컬 좌표계를 월드 좌표계로 변환해 준다. 
        - 월드 좌표계: 절대 좌표인 월드 좌표계의 위치로부터 각 물체의 상대적 위치 값을 의미
        - 월드 좌표계에서는 실제 이 월드의 중심점이 0, 0, 0이며, 다른 물체들은 여기서 얼마나 떨어져 있는지로 표현됨.

        - 여기서 각 오브젝트들은 더 이상 자기가 세상의 중심이 아니란 것을 알게 된다.
        - 유니티에서는 이 월드(world) 좌표계를 '모델(Model)'이라고 부름
        - 그렇지만 여전히 카메라가 없기 때문에 화면에 출력할 수 없는 상태.

 

 

 

 

    (3) 카메라 (뷰/시선) 좌표계

        - 월드 행렬로 변화된 물체들은 이제 이 월드에 위치 값을 가지게 되었다.

        - but 여기에 아직 고려되지 않은 게 있다. 바로 '카메라'! 월드에 존재하는 것은 카메라가 없으면 화면에 보일 수 X
        - 월드 좌표계의 버텍스들은 다시 '카메라 행렬'로 곱해서

          월드 좌표계에서 오브젝트의 버텍스 위치 값들이 카메라의 중심점으로부터의 상대적 거리로 다시 연산된다.
        - 즉, 여기에서는 카메라 중심점이 0, 0, 0이며, 다른 물체들은 여기에서 얼마나 상대적으로 떨어져 있는지로 표현

        - 드디어 물체들은 화면에 볼 수 있게 되었지만, 원근감을 고려 X
        - 카메라 행렬은 뷰(View)라고 불리며, 오쏘그래픽 프로젝션(Orthographic Projection)이라 불리기도 한다.
        - 그리고 이 시점부터 모니터에 출력하는 것이 가능한 상태가 된다. 카메라가 있으니!

 

 

 

    (4) 프로젝션 좌표계

        - 이렇게 카메라 행렬로 정렬된 버텍스 들은 다시 한번 '프로젝션 (Projection) 행렬'로 곱해진다. 
          ㄴ 이 경우는 퍼스펙티브(perspective) 프로젝션일 경우에 일어나는 순서이고, 
              오쏘그래픽 프로젝션의 경우에서는 일어나지 않는 순서다.
              Perspective 프로젝션을 사용하는 것이 일반적이므로 이렇게 설명하였다.
        - '프로젝션 행렬'이란 원근감을 부여해 주기 위한 방법으로,

           카메라에서 먼 곳은 좁혀진 것처럼 버택스 위치를 조정해 주는 것
        -  사실상 카메라에서 멀수록 크기가 작아지는 물체가 된다. 그리고 우리가 흔히 볼 수 있는 뷰의 모습이 된다.

 

 

 

     - 여기까지 작업을 그대로 모니터에 출력한다면 여전히 텍스쳐도 음영도 없는, 말 그대로 폴리곤 덩어리가 생성된다.
     - 화면에 찍힐 수 있는 준비는 되었지만, 이 오브젝트는 아직 픽셀 쉐이더를 거치지 않았기 때문에

       결과적으로 우리가 모니터로 볼 수도 없는 단지 3D 공간에서 존재하는 오브젝트일 뿐

 

 

 

 

 

    [ 추가 노트 ] 
 


사진출처: https://github.com/medialab-ku/openGLESbook   

 
  - 렌더링 파이프라인을 깊게 이해하고 싶다면 들어가셔서 자료를 살펴보세요!

 

 

 


 

 

 

 

3) 래스터라이저 (Rasterizer)

     - 좌표계가 조정된 버텍스를 이용해서 화면에 오브젝트를 출력할 준비가 되었다.
     - 이번에는 진짜 모니터에 이 오브젝트를 출력해 줄 것이다. 
     - 그래서 이 오브젝트가 모니터에서 표현될 때 어느 픽셀로 표현될 것인지를 나타내는 장치를 거치게 되는데
       이것을 래스터라이져라 부르며, 2D 픽셀로 표현되는 세계로 넘어오게 된다.

     - 3D 오브젝트는 모니터에서 보이도록 'pixel'이 되었고 이 과정을 '래스터화'라고 한다.
     - 3D로 있던 '석고상'을 촬영하는 순간 그 석고상은 2D 이미지가 되듯이, 3D 이미지가 2D 이미지가 되는 순간이다.
     - 모니터에 보이려면 2D 이미지로 만들어야 하니 말이다. 이 모든 작업이 매 프레임마다 일어나는 것이다.

     - 이렇게 수학적인 가상공간 안에서 입체로 떠돌던 오브젝트는 픽셀이 되고,

         드디어 픽셀쉐이더에서 이 픽셀에 접근할 수 있게 되었다.

    - 최근 Direct-x에서는 여기에 여러 가지의 쉐이더가 추가로 들어간다. 

      vertex shader와 pixel shader 중간에 위치하는 이 쉐이더는 헐 쉐이더(Hull Shader), 테셀쉐이더(Tessellator),

      도메인 쉐이더(Domain Shader), 지오메트리 쉐이더(Geometry Shader), 컴퓨트 쉐이더(Compute Shader)등이 있다.
 
     - 이 모든 작업들이 매 프레임마다 일어난다.

        당연히 화면에는 버텍스보다 픽셀이 더 많으니 픽셀 셰이더가 버텍스 셰이더보다 더 무겁다.

 

 

 


 

 

 

4) 픽셀쉐이더 (Pixel Shader) / 프레그먼트 쉐이더 (Fragment Shader)

- 이렇게 모니터까지 넘어온 3D 그래픽 데이터는 본격적으로 화면에 픽셀로 찍히게 된다. 
- 물론 아직 텍스쳐도 없고 라이팅도 없는 상태다. (vertex shader 단계에서 라이팅을 연산하지 않았다면)

- 이제 여기에서 픽셀 셰이더가 가동되면서 조명과 텍스쳐, 그림자와 각종 특수효과 등을 연산하게 되는 것.
- 프레그먼트 셰이더는 픽셀보다도 더 상위의 개념을 말하는 용어
- 이제 막 시작하는 입장에서 픽셀과 거의 동일하다는 생각으로 시작해도 무방

 

- 물론 실제 렌더링 프로세스가 이렇게 간략하진 않음. 

  그래픽 아티스트 입장에서는 일단 여기까지만 알아도 별 문제가 없음

- 이 부분 어렵고 잘 모르겠다면 넘어다도 된다! 괜찮다!!

  정확함을 추구하다 흥미 잃어버리는 것보다 우선 적당히 알면서 흥미 있게 배우는 것이 더 중요!

 

 

 

 


 

* 삽입되는 이미지는 출처표기 없으면 제가 실습해서 캡쳐한 것입니다.

 

 

 

+ 대마왕님 책을 읽으면 더 쉽게 이해하실 수 있습니다.

+ 렌더링 파이프라인 이해해 도움이 되는 레트로님의 유튜브도 추천합니다.

 

https://youtu.be/0XJWdNFnq50

 

댓글