들어가며


안녕하세요 이번 글은 그래픽스와 관련하여 서술하게 되었습니다.

제가 어제 기업 직무 테스트를 치르고 왔는데 그래픽스와 관련하여 모르는 내용이 많은 것을 확인하였습니다.

그래서 고려대 그래픽스 강의를 참고하여 관련 내용을 정리해보려고 합니다.


GPU Rendering Pipeline


컴퓨터 그래픽스의 목표는 컴퓨터 안에 있는 3차원 공간을 우리가 보는 화면인 2차원 디스플레이에 표현하는 것입니다. 영화를 만들고 그림을 그리는 것처럼 말입니다.

우리는 여러가지 과정을 거쳐서 이를 실현 가능한데 이 과정을 렌더링 파이프라인(Rendering Pipeline)이라고 합니다.

렌더링 파이프라인은 총 네가지의 과정으로 구성됩니다.

  1. Vertex Shader
  2. Rasterizer
  3. Fragment Shader
  4. Output merger

위 네 가지 과정은 이름부터 생소하신 분들도 많으실텐데요, 알아보면 전혀 어렵지않은 내용입니다.

우선 각 과정에 대해 세세하게 접근하기 전에 대략적인 역할만 알아보겠습니다.

렌더링 파이프라인은 영화를 찍는 과정과 유사합니다.

영화를 찍으려면 배우, 소품들을 배치하고 그것을 카메라로 찍죠. 그러면 특정 화면이 뽑히는 것이고요. 렌더링 파이프라인을 같은 목표를 가지고 있지만 살짝 더 복잡한 과정을 통해 목표를 이룹니다.

우선 1번 Vertex Shader는 3차원 공간에 모델들을 배치한 후 특정 위치에 카메라를 가져다놓고, 카메라를 통해 보고싶은 특정 공간의 정보를 가져옵니다.

영화를 찍는 것과 약간 다른 것은 이때까지는 아직 색과 빛 없이, 형체만 가져옵니다.

그 다음 Rasterizer 과정은 가져온 공간 정보에 사후 처리와 3번 과정을 위한 처리를 해주는 과정입니다.

3번 Fragment Shader에서는 이렇게 뽑힌 이미지에 텍스쳐와 빛을 입히게 됩니다.

마지막으로 4번 Output merger에서 다듬기 과정을 통해 정확한 이미지를 그려낸다고 보시면 됩니다.


1. Vertex Shader

그러면 이제 Vertex Shader에 대해서 좀 더 알아보겠습니다.

우선 Shader라는 단어는 그냥 Program이라고 생각하시면 됩니다. 저희가 직접 짜야하는 부분인 것이죠. 이에 반해 2, 4번의 Rasterizer와 Output merger는 하드웨어 파트입니다.

앞서서 Vertex Shader는 3차원 공간에 모델들을 배치한 후 특정 위치에 카메라를 가져다놓고, 카메라를 통해 보고싶은 특정 공간정보를 가져오는 과정이라고 했습니다. 마치 아래의 그림처럼 말입니다.

우선 이 정보라는 것이 무엇인지 알기 위해서는 3차원 공간 상에 배치된 모델이 어떻게 구성되어있는지 이해해야 합니다.

컴퓨터 그래픽에서 모델은 아래와 같이 PolygonVertex들로 이루어져있는데 이를 합쳐 Polygon Mesh라고 합니다.

여기서 Polygon은 다각형을 의미하는데 보통은 삼각형을 의미하며 Vertex는 말그대로 모델에서의 각 점들을 의미합니다. 이 Vertex에 관해서 중요한 정보는 x, y, z 위치 좌표와 normal 벡터입니다.

그리고 이 정보가 제가 앞서서 말씀드린 정보입니다.

Vertex Shader의 이름에서 유추하실 수 있겠지만 그래서 궁극적으로 Vertex Shader가 하고자하는 것은 우리가 보고자 하는 특정 공간에 있는 Vertex들의 정보를 잘 가져오자는 것입니다.

이제 대략적으로 어떤 Vertex Shader가 어떤 것을 하고자 하는지 감이 오실 것입니다. 그러면 좀 더 자세히 들어가보죠.

유니티를 사용해보시거나 한번이라도 보신 분들은 유니티 안에 3d 공간이 있는 것을 아실 것입니다.

그 공간 안에 여러 오브젝트들이 배치되어 있고요.

이런 3d 공간을 World space라고 부릅니다. 여러 오브젝트들이 있는 하나의 세계인 것이죠. 아래와 같이 말입니다.

그런데 이건 그냥 3d 공간일 뿐이고 저희가 원하는 건 특정 위치, 각도에서 바라본 화면입니다.

이를 위해서는 카메라가 필요하겠죠. 그래서 다음과 같이 카메라를 설정할 수 있습니다.

그리고 이런 저런 오브젝트들은 앞서 말씀드렸듯 전부 Polygon mesh로 이루어져있습니다.

World space에 오브젝트들이 있지만 저희가 원하는 건 그냥 저 카메라로 본 화면일 뿐입니다. 아래와 같이 말이죠.

이러한 화면을 구성하기 위해서 어떤 정보가 필요할까요? vertex들의 좌표일 것입니다. 그런데 지금은 vertex들이 world space의 좌표계를 기준으로 좌표값을 가지고 있습니다.

하지만 위와 같은 화면을 구성하기 위해서는 카메라를 기준으로 하는 좌표가 필요하지 않을까요?

그래서 여기서 view transform이라고하는 좌표계 변환이 일어나게 됩니다.

그 과정은 아래의 그림과 같은데요, (10, 2, 0)었던 좌표값을 (0, 0, -10)으로 설정해주는 것이죠.

이렇게 한번의 변환이 일어나게 되면 우리는 world space에서 camera space로 이동했다고 말합니다.

이렇게 모든 좌표를 카메라 좌표계를 기준으로 설정해준 후, 카메라에 보이는 영역 외의 영역은 지워버립니다. 어차피 보이지 않으니까요.

이 때, 카메라에 보이는 영역을 view frustum이라고 하고, 위의 유니티 카메라에서 뻗어져나오는 피라미드 형태를 의미합니다.

여기까지 했으면 이제 3d 공간에서 카메라로 보고싶은 영역의 정보만 잘 처리한 것 같습니다. 그러나 아직 끝은 아닙니다.

camera space에 있는 좌표값들을 그대로 사용하게되면 원근법이 적용되지않기에, 이를 적용하기 위해 projection transform이라는 변환을 적용해서 원근법이 적용된 좌표값으로 바꿔줍니다. 그러면 이제 clip space라고 하는 공간으로 이동한 것입니다.

이렇게까지 정점의 좌표들을 처리해주면 이제 vertex shader의 역할은 끝입니다.

이제 이 좌표들의 정보를 가지고 나머지 처리들이 이뤄지게되는데 그 부분은 다음 글에서 다루겠습니다.