01. 3D 그래픽의 이해



1. 3D 그래픽 파이프라인



1.1 게임 엔진을 구성하는 소스코드 모듈들

- User Input (사용자 입력)

- Resource Management (자원 관리)

- Loading and Rendering Graphics (그래픽 로딩과 렌더링)

- Interpreting and Executing Scripts (스크립트 해석과 실행)

- Playing Sound Effects (음향 처리)

- Artificial Intelligence (인공 지능)



1.4 좌표계

- Mesh (3차원 공간상의 객체) 를 기하학적으로 표현하기 위해선 좌표계가 필요하다.

- 2차원 좌표계(2차원 직교 좌표계, 화면(스크린) 좌표계), 3차원 좌표계(왼손 좌표계, 오른손 좌표계)

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)


(출처 : http://blog.daum.net/jty71/15645437)



- 모델(or 지역) 좌표계와 월드 좌표계

- 모델 좌표계 : 객체의 지역적 공간(Local space)을 표현하는 좌표계(모델마다 별도의 좌표계를 갖고 있다고 가정)

- 월드 좌표계 : 게임 세계 전체를 하나의 통일된 좌표계로 표현하기 위한 좌표계(전역 좌표계)

(출처 : http://msdn.microsoft.com/en-us/library/windows/desktop/bb206365(v=vs.85).aspx)



1.5 와인딩 순서(Winding Order)

- Mesh 를 구성하는 다각형의 정점들을 나열하는 순서. 

즉, 다각형의 정점 or 모서리가 어떤 순서로 연결되는지를 나타냄.

- 은면(Back Face Culling : 카메라에서 보이지 않는 면) 제거를 수행하기 위해 사용한다.

- 시계 방향, 반시계 방향 순서가 있는데 Direct3D는 기본적으로 시계방향. (보통 반시계가 기본임)

Direct3D 기준으로 눈에 보이는 면들이 시계방향으로 와인딩 되기 때문에 
보이지 않는 면의 경우 반시계방향으로 와인딩 된다고 할 수 있다.

(출처 : http://cookiejeon.tistory.com/3)



1.6 화면 렌더링

- 화가의 알고리즘(Painter's Algorithm) : 3차원 세상을 2차원 평면에 그리는 과정이나 비효율적.

 자세한 내용은 위키백과.

http://ko.wikipedia.org/wiki/%ED%99%94%EA%B0%80_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98 )





2. 변환 파이프라인


① 정점(지역 좌표계)

월드 변환 (World Transformation)

② 월드 좌표계

카메라 변환 (View, Camera Transformation)

③ 카메라 좌표계

------------------------------------------------ ↑ 3D, ↓2D 좌표

투영 변환 (Projection Transformation)

④ 투영 좌표계

화면 변환 (Screen Transformation)

⑤ 화면 좌표계



* 참고로 Primitive Transformation 에는 3가지 종류가 있다.

1) Translation (이동)   2) Rotation (회전)   3) Scaling (크기)

(관련 링크 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729722.aspx)



# 월드 변환(World Transformation)

- 회전 변환 + 평행이동 변환을 통해 지역 좌표계로 표현된 객체의 Mesh 가 월드 좌표계로 변환되는 과정

(회전 변환 계산법 생략*), (회전을 먼저 하냐 평행을 먼저 하냐에 따라 결과가 다르다는 점 주의)

(출처 : http://goldface.tistory.com/archive/20120205)


# 카메라 변환(View, Camera Transformation)

- 월드 좌표계로 변환된 정점을 카메라 좌표계로 변환하는 것을 말한다.

- 3차원 공간이 투영되어 가상 카메라에 나타나는 2차원 평면을 카메라 평면이라 한다.

- 가상 카메라는 위치, 방향, FOV(Field of View) 와 같은 속성을 가진다.

※ FOV : 특정 방향과 특정 위치에서 어떤 물체가 보이는 지를 말한다. 

   사람의 경우 앞(Forward)을 향해 FOV를 가지고 있다. 그래서 자신의 뒤에 무엇이 있는지 볼 수 없다.

※ 화각(Viewing Angle) : 카메라에서 볼 수 있는 각도, 화각에 따라 FOV 공간의 형태가 달라진다.

아래 그림에서 Θ에 해당한다.


사람은 너무 가깝거나 or 너무 멀거나 하는 물체는 제대로 볼 수 없다.

그래서 컴퓨터 그래픽에서는 이 FOV 를 다음과 같이 View Frustum 으로 표현한다.


View Frustum 은 총 6개의 면으로 이루어져 있고 그 중 2 개는 XY 평면과 평행하다.

아래 그림에서 a 면이 Near-Z, b 면이 Far-Z 평면이라 불린다.

FOV 가 넓을수록 View Frustum 의 부피도 커지고 그만큼 시야가 넓어지는 것을 의미한다.


보통 좌표계에서 Z 축이 Forward 방향을 나타낸다. (X 축이 좌우, Y 축이 상하, Z 축이 앞뒤)

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)

- 카메라 변환 과정

1) 카메라를 월드 좌표계의 원점으로 평행이동

2) 1)과 같은 변환을 게임 세계의 모든 객체에 적용

3) 카메라 좌표계 축들이 월드 좌표계 축들과 일치하도록 회전 변환

4) 3)과 같은 변환을 게임 세계의 모든 객체에 적용

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)



# 투영 변환(Projection Transformation)

- 카메라 좌표계에서 카메라에 보이는 객체에 대하여 카메라와 객체까지의 거리는 기본적으로 Z 좌표로 근사할 수 있다.

- 카메라와 Mesh 사이의 Z 좌표가 증가할 때 메시의 각 정점 X, Y 좌표를 Z 좌표(ViewSpaceZ)의 z 값에 반비례하도록

변환하면 원근 효과를 나타낼 수 있다.

- 카메라 FOV 공간에 있는 정점들이 투영되는 공간은 투영 윈도우(Projection Window) 라고 한다.

-1 <= X <= 1, -1 <= Y <= 1 :: 카메라 FOV 공간에 포함된 정점들을 투영 변환했을 때 값들의 범위

(그외의 값을 갖는 점들은 카메라 FOV 공간에 포함되지 않아 보이지 않음)

- 투영 변환 :

X(projected) = x / ( z / d )

Y(projected) = y / ( z / d )

d 는 카메라에서 투영 평면까지의 거리를 의미한다.

d = 1 인 경우는 FOV 의 화각이 90도인 경우를 말한다. Direct3D의 경우 항상 1.0 의 값으로 설정.

- 쉽게 설명하자면,

투영 변환이란 3D 좌표 → 2D 좌표로 바꾸는 작업이다. 그러면 어떻게 바꾸냐?

FOV 의 화각이 90도 라고 했을 때(d=1),

(x, y, z) → (x/z, y/z, z/z) → (x/z, y,z, 1) 으로 바꿔버린다.

그러면 모든 정점들의 Z 좌표 값이 모두 1이 될 것이다. 

즉, 한 평면에 모든 정점들이 표현되고 이는 2D 좌표와 다를 것이 없다.


여기서 중요한 건 d=1 이라는 가정이다. 정확히는 z / (z/d) = 1 / d 가 되어

투영 변환된 Z좌표의 값은 0 <= Z <= 1 값을 갖게 될 것이다.

'그러면 2D가 아니지 않느냐?' 라고 생각할 수 있는데 왜 이렇게 되어야 하는 지는

Z-Buffer 얘기를 해야하는데 위에 '화가의 알고리즘' 관련 링크를 따라가 보면 알 수 있다 :-)



# 화면 변환(Screen Transformation)

- 투영 변환을 거친 정점은 2차원 좌표라고 생각할 수 있다.

이러한 2차원 좌표를 화면 좌표계로 변환하여 2차원 화면의 Pixel 로 그리는 단계.

- 렌더링할 대상의 화면 영역을 뷰포트(Viewport) 라고 한다.

(출처 : http://www.asksatyam.com/2011/01/window-to-viewporttransformation.html)


아무리 비율 좋은 Mesh 라고 한다고 해도 화면 비율에 맞게 렌더링 하다보면

위와 같은 현상이 나타날 수 있다. 그러니 다음과 같은 식을 이용한다.


- 픽셀 위치 좌표계 :

ScreenX = projVertex.x * (ViewportWidth / 2) + ViewportLeft + (ViewportWidth / 2)

ScreenY = - projVertex.y * (ViewportHeight / 2) + ViewportTop + (ViewportHeight /2)


ViewportLeft, ViewportTop : 뷰포트의 원점 위치

ViewportWidth, ViewportHeight : 뷰포트 가로, 세로 크기

※ 투영 좌표계는 좌표계 한가운데가 원점인 직교 좌표계이고, 

뷰포트는 왼쪽 상단이 원점인 좌표계이므로 Y 축의 방향이 서로 반대 방향이라 (-) 부호를 붙인다.




Transformation Pipeline 의 흐름을 잘 이해할 수 있는 이미지를 가져와봤다.

(출처 : https://forum.libcinder.org/topic/finding-an-object-s-screen-coordinates)



* 그 외 참조 :

http://code.msdn.microsoft.com/windowsapps/Direct3D-Tutorial-Win32-829979ef


by kelicia 2014. 7. 21. 21:11
| 1 |