[컴퓨터 그래픽스] 7장 Rasterizer

함지율·2024년 4월 14일

컴퓨터 그래픽스

목록 보기
4/5

Rasterizer

Object space를 vertex shader를 clip space로 만들고 rasterizer에 넘겨줍니다. rasterizer는 삼각형을 모아서 fragment를 만드는 역할을 합니다.

rasterzier에서는 여러 가지 일을 하는데 크게 5가지 단계를 수행합니다.

  • Clipping
  • Perspective division
  • Back-face culling
  • Viewport transform
  • Scan conversion

Clipping

t1아예 버리고 t2는 완전히 save하면 됩니다. t3는 view frustum밖으로 나가는 부분은 clip하는 과정이 필요합니다. 이 부분은 하드웨어가 알아서 잘 처리해줍니다.

Perspective Division

projection 행렬은 마지막 원소가 -z로 나오기 때문에 -z로 나눠주면 카테시안 좌표로 쉽게 구할 수 있습니다. 우리는 여기서 실제 -z가 어떤 역할을 하는 지 살펴보겠습니다.

아래의 그림처럼 fovy, aspect, n, f를 통해 view frustum을 쉽게 구할 수 있습니다. projection matrix를 camer space의 점을 통과시키면 clip space의 좌표가 나옵니다. 이때, l1, l2를 비교해보면 l1은 w=2, l2는 w=1이 나옵니다. w=-z인데 해당 좌표는 -z축 방향 좌표이기에 단순히 거리라고 판단할 수 있습니다. 해당 값은 image plane으로 부터 얼마나 떨어져있는지 거리를 나타냅니다. 멀리 떨어져 있을 수록 크기는 작아지게됩니다. 이는 원근법을 반영한 나눗셈임으로 perspective division이라고 합니다. 원근 투영의 핵심 개념입니다.

Back-face Culling

카메라를 등지고 있는 삼각형같은 경우 back-face라고 합니다. 그리고 이러한 부분을 버린다고 하여 culling 이라고 합니다. 그러면 back-face와 front-face를 어떻게 구분할까요?

n3가 카메라 시점에서 선분으로 보인다면, n3 삼각형 normal과 카메라를 향하는 벡터를 내적하면 0이 나옵니다. t2는 내적값이 양수값가 나옵니다. 반면 n1은 내적이 음수값이 나옵니다. 그렇다면 양수는 취하고 음수는 버리면 됩니다.
실제 구현은 이미 camera space가 아닌 clip space이기 때문에 약간 다릅니다.

clip space에서는 universal projection line이 표현됩니다. 하지만, 이 보다 더 간단히 계산할 수 있습니다.

시계 방향 반시계 방향으로 구분할 수 있습니다. 좌표가 시계방향이면 back-face 반시계는 front-face입니다. 이를 컴퓨터에 알려줄 수 있는 방법은 간단한 행렬식의 부호로 알려줄 수 있습니다.

행렬식이 양수일 경우 CCW이며 front face, 음수일 경우 CW이며 back face입니다.

컴퓨터에서는 복잡하게 내적할 필요없이 단순히 행렬식 계산으로 back-face 제거를 할 수 있습니다.


하지만, 만약에 반투명 구일 경우에는 back-face를 살려놔야합니다. 또는 반대로 front-face를 없앤다고 하면 구의 단면을 볼 수 있습니다. 따라서, 여러 경우에 따라 사용자들이 선택할 수 있도록 API를 열어두었습니다.

back-face를 할지 말지는 glEnable, glDisable을 통해 선택할 수 있습니다. default는 비활성화로 되어있고 활성화하기 위해서는 glEnable(GL_CULL_FACE)처럼 호출해주어야합니다. 이제 어떤 면을 없앨지

  • GL_FRONT
  • GL_BACK
  • GL_FRONT_AND_BACK

으로 선택할 수 있습니다.

이제 무엇을 back으로 설정할지는 glFrontFace()로 지정할 수 있습니다.

  • GL_CW
  • GL_CCW

로 지정할 수 있으면 default는 GL_CCW입니다.

원래 rasterizer는 하드웨어에서 수행되기에 손을 못대지만 culling은 약간 자유도를 주었습니다.

Viewport

viewport transform을 정의하기전에 viewport에 대해서 알아봅시다. window는 computer screen이고 이를 window space라고 합니다. 이런 window를 항상 꽉 채워 볼 필요는 없습니다. 4등분해서 서로 다른 view를 채울 수 있는거죠. 실제 window에서 내가 그림을 그릴 영역을 viewport라고 합니다. viewport는 시작점 minX, minY, W(idth), H(eight) 만 알면 사각형을 정의할 수 있습니다.

screen space와 viewport는 모두 3차원 공간입니다. (실제로 바라보는 모니터가 2차원처럼 보이지만 사실은 3차원입니다.)


위의 그림에서 볼 수 있듯 screen은 3차원 공간이고 LHS(왼손 좌표계)를 따르는 것을 알 수 있습니다.

아래의 코드로 구현할 수 있습니다.

지금까지 했던 변환을 정리하면

Object Space \rightarrow (world transform) World Space \rightarrow (view transform) Camera Space \rightarrow (projection transform) Clip Space \rightarrow viewport transform, VPT) Screen Space

앞에서 clip space에서 이미 LHS로 변환해주었기 때문에 추가적인 변환은 해주지 않아도 되는 편리함이 있습니다.

NDC = x,y,z 모두 2x2x2 크기를 가지는 -1~1 범위를 갖는 정육면체인데, screen space는 wxhxdepth를 갖는 직육면체입니다. 이를 어떻게 변환해주면 될까요?

이러한 scaling을 통해 크기를 바꾸고 원점을 옮겨주기 위해 translation 연산을 거치면 NDC에서 screen space로 변환할 수 있습니다.

대부분 minZ, maxZ가 각각 0.0, 1.0이고 minX, minY 또한 0이기 때문에 아래와 같이 나타낼 수 있습니다.

이해하기 쉽게 box로 모두 표현이 되어 있는데 사실 이러한 box는 이해를 돕기 위해 사용된 것이고 실제로 polygon mesh에 직접 적용됩니다.

Vertex Shader (revisited)

gl_Position까지는 vertex space가 수행했고 clip space로 나오면 rasterizer가 perspective division을 통해 NDC로 보냅니다. 최종적으로 viewport transform에 의해 screen space로 보냅니다.

위의 코드에서 normal은 왜 world space까지만 변환했을까요? 이는 9장에서 배웁니다. texCoord는 그냥 copy해서 가지고 있습니다.

가만보니 normal과 texCoord는 아무것도 건들지 않았습니다. 이를 rasterizer에서 처리하는 단계가 Scan conversion 입니다.

Scan Conversion

mesh가 screen space에 위치해 있을 때 실제 2D 스크린에는 아래의 그림처럼 보입니다. 여기서 중요한 개념은 선형 보간 개념입니다.

선형 보간은 아래의 그림처럼 나타내어질 수 있습니다.

이제 다시 screen space로 돌아와서 보겠습니다. 각 픽셀마다 예로 RGB값이 있고 여기서는 R값만 다루어보겠습니다. 각 픽셀에서 R값이 정해져 있을겁니다. scan line이라는 격자가 이루어지고 격자 안이 pixel 입니다. 따라서 pixel마다 보간하고자 합니다.


그림을 보면서 생각을 해보겠습니다. R값의 변화량과 y좌표의 변화량을 구하고 y 변화량 당 R값의 변화량을 구하면 y값이 1 증가할 때 R값이 얼마나 증가하는지 알 수 있습니다.

y변화량 당 x변화량을 구하면 y가 1 증가할 때 x좌표가 얼마나 변화하는지 구할 수 있습니다.

이렇게 구한 변화량을 scan line에 맞춰 초기 조건에 따라 값을 보간해주면 나머지 값은 y에 따른 1 변화량에 따라 보간해주면 됩니다.

이를 각 vertex position을 이은 선분 마다 수행합니다. (여기서는 삼각형이기에 3번 수행합니다.)

그 후 중간에 있는 점은 x에 대한 변화량을 구하여 보간할 수 있습니다.

  1. 선분을 따라 선형 보간
  2. 그 결과를 통해 x축을 통해 선형 보간
    => bilinear interpolation

Normal Interpolation

normal 또한 방금 보았던 bilinear interpolation을 통해서 보간할 수 있습니다.

normal과 texCoord가 보간되어 저장되어있고 이를 fragment라고 합니다. fragment shader에서는 보간된 normal과 texCoord을 가지고 실제 색상을 정의합니다.

다음은 이미지 텍스처링에 대해서 공부해보겠습니다.

Scan Conversion Appendix


참고자료
고려대학교 정보대학 한정현 교수님 강의

profile
꿈 꾸는 디그다

0개의 댓글