[DirectX11 Pipeline] 2. Vertex Shader

SYiee·2023년 8월 7일
1
post-thumbnail

🖤Vertex Shader

💡 요약
Input Assembler 로부터 primitives input으로 받아 object space -> world space -> camera space -> clip space 로 보내 최종 output으로 모니터에 보이는 final position을 구하는 단계이다.

  • programmable sections

    → 어떻게 동작할지 만들 수 있다는 것을 의미한다. 코딩이 가능하다.

  • shader : program이다.

  • gpu는 병렬처리로 고속 floating point 연산이 가능하다.

    → floating point : gpu가 그래픽스 하기에 벡터 연산이 많아 floating point를 빠르게 처리할 수 있는 core가 많다. 반면 cpu는 int연산을 하는 unit이 많아 int연산이 빠르다.

    ⇒ 이로 인해 가이드 라인을 따라줘야 한다.

    • 내부에서 뭘 하든 VS의 input & output 규약을 따라야한다.
  • 총 다섯개의 shader stage가 있다.

    → 그 중 VS는 뺄 수 없는 단계이다.

    • 그림에서 연한 연두색은 빼도 상관이 없다.

    • 초록색은 무조건 들어가야 하는 것들 이다

      ⇒ vertex shader is a required shader stage.

DX9부터 필요에 의해 셰이더를 하나씩 추가하기 시작했다.

  • GPU 파이프 라인이 한 번 돌아야 한 프레임이 표현된다.

  • 모든 vertex마다 한번씩 돈다. ⇒ per vertex operation

  • 특성) "내 옆에 있는 애의 정보는 참조할 수 없다!"

    • 모두 한 번의 클락 사이클 내에 처리 되기 때문에 옆에 정점의 정보와는 독립적으로 처리된다.
    • for문 자체가 멀티사이클을 필요로 한다. 이전의 오퍼레이션이 다음 for문에 쓰이는데 이런 개념 자체가 gpu에서는 불가능하다. 즉, 앞쪽에 있는 연산의 dependency가 있으면 안된다.

📌 space & Transform

Transform → matrix multiplexion

Object space (=model space)

  • 오브젝트를 정의할 때 쓰는 공간
  • object의 point of view에서 정의한 좌표계
  • to world space : 물체마다 다르다. transform이 물체마다 정의된다

world transform MwM_w

World space

  • 3D world를 정의하는 봐표계
  • This is the coordinate system defining a 3D world

view transform MvM_v

Camera space (=eye space)

  • 카메라가 바라보는 위치에서 정의한 좌표계 This is the coordinate system defined by an camera’s point of view

projection transform MpM_p

Clip space

  • This is the coordinate system defined by performing a projection transform to the points in the camera space
  • 카메라 스페이스에서 projection transform을 수행한 좌표계

⇒ 이 세개의 매트릭스가 모두 합쳐지게 된다. object space에서 clip space로 한 번에 보내게 되고 이게 VS의 최종 아웃풋이 final position이 된다.

✔ World Transform

  • 모든 오브젝트를 동일한 공간으로 가지고 온다.
    각각의 오브젝트는 자신만의 오브젝트 스페이스를 가지고 있는데 이를 single coordinate system으로 assemble하는 것이다.

  • vertex를 돌리면 nomal도 같이 움직여야 한다.
  • 그러나 nomal에 대한 정보는 vertex 정보가 GPU에 들어올 때 같이 들어오게 된다.
    → GPU에서는 옆에 있는 애의 정보를 참조할 수 없기 때문에 CPU에서 다 계산을 해서 넘겨주게 된다.
  • 근데 여기에 문제가 있다.
    → L includes a non-uniform scaling, it cannot be applied to surface normal

  • 이를 해결하기 위해 (L1)T(L^{-1})^T 를 사용한다.

⇒ nomal은 앞으로 무조건 (L1)T(L^{-1})^T 사용하고 nomalize 한다.

🌊 EX) Consider the triangle (p, q, r) and its normal n.

n이라는 노멀 벡터 와 (q-p) 벡터를 dot product하면 0이 된다. 수직이니까.
nTn^T를 한 것은 col 벡터를 만들어주기 위함이다.

linear transform L 을 곱하면 각 정점들이 바뀌게 된다.

⇒ nomal과 관련된 식에서 성립을 하려면 L의 inverse가 나올 수 밖에 없구나!

식을 정리하면 다음과 같다. (L1)T(L^{-1})^T이 나오는 이유

✔ View Transform

the camera is also an object, it is defined in the world space

Camera pose specification in the world space is as follows:

  • EYE: camera position
    카메라의 위치
  • AT: a reference point toward which the camera is aimed
    카메라가 어디를 바라보고 있는가
  • UP: view up vector that describes where the top of the camera is pointing.
    (In most cases, UP is set to the vertical axis, y-axis, of the world space.)
    카메라의 윗 부분이 어디인가.
  • uvn은 서로 직교하고 1의 크기

  • n : 카메라가 바라보는 방향
  • v : n x up
  • v : n x u

  • 예를 들어 월드 스페이스에서는 (0, 2, 10) 인데 카메라 스페이스 관점에서는 (0,0,10)이다.

⇒ 변환하는 transform mat를 찾고자한다.

space change

  • world space → camera space

  1. First, EYE is translated to the origin of the world space.
    → DirectX는 row major이라 매트릭스가 다 transpode 된 형태로 나온다.
  1. Rotation
    basis가 어떻게 되어 있는지 최종 꼴을 알고 있으면 uvn을 그냥 써서 구할 수 있다. 이것을 이용 한다.

view matrix

DirectX : v1TRv_1TR

→ 순서에 유의하자

✔ Projection Transform

: 2D 모니터에 상이 맺히는 과정

View Frustum

view frustum

카메라는 무한한 공간을 보지 않는다. 관심 있는 영역 내에 있는 것만 보기 위해 관심 있는 영역만 자르게 되는데 이것을 view frustum 이라고 한다.

View Frustum은 fovy, aspect, n, f 이렇게 4가지 변수가 있는데, fovy보는 시야각, aspect넓이와 높이의 비율, n가장 가까운 시점, f가장 먼 시점을 나타낸다. 이 변수들을 이용하면 아래와 같이 사다리꼴 또는 사각뿔이 잘린 거 같은 공간을 정의할 수 있다. 이 안에 있는 object만 camera가 담을 수 있다는 의미이기도 한다.

field of view

얼마나 넓게 볼 것인가

  • 너무넓으면 → 퍼포먼스가 크고 왜곡이 생긴다
  • 너무 좁게 → 가까이에 있는 것도 안 보인다.

⇒ 적당히 설정해야한다.

💡 View frustum culling

CPU에서 이루어지는 전처리 과정

  • View frustum 안에 들어와 있지 않은 것은 gpu pipeline에 들어오기 전에 잘라 버린다.
    [ 방법 ]
    1. cpu에서 러프하게. 너무 멀리 있는 것 같으면 gpu 메모리에도 올리지 않는다.
    2. VS에서 계산을 해서 다음 스테이지 넘어갈 때 자른다.
  • 필요없는 것을 잘라내니 computational power of GPU 올라간다.

💡 Clipping
resterization 단계에서 이루어진다.

view frustum의 boundary에 걸리면 boundary를 기준으로 잘라야한다. 잘린 부분은 잘라서 프로세스를 안할 것이다. 근데 이게 생각보다 쉽지 않다.

잘린 위치에서 vertex를 새로 생성해 primitive를 만드는 과정이 들어가야 하기 때문이다. 이와 관련된 내용은 뒷 부분에서 상세히 다루도록 하니 넘어가겠다.

Projection transform and clip space

  • clipping을 할 때 pyramidal view frustumd을 사용하지 않고 대신 2×2×1-sized cube로 끌고 오게 되는데 이 과정을 projection transform라고 부른다.
  • 큐브를 기준으로 자르게 된다.
  • 그러면 clip space로 가게 된다.

View frustum to cube

  • perspective projection을 내포
    → 멀리 있는 것은 작게 가까이 있는 것은 크게
  • z-axis을 기준으로 평행하게 만들어진다.

Projection Matrix


🖇 Reference

해당 포스트는 강형엽 교수님게임그래스프로그래밍 [GGP-23-1] 수업을 수강하고 정리한 내용입니다. 잘못된 내용이 있다면 댓글로 알려주시면 감사하겠습니다😊

profile
게임 개발자

0개의 댓글