Computer Game Architecture 1 - OpenGL components & Transformation

Game components : Interactive Graphics, modeling, UI, sound, event handling, network, AI

Game Architecture Components
- Resources : game assets that show in the scene
- Low level renderer :shader, camera, fonts
- Scene graph : manage objects in the scene
- Visual effects : particle system, shadows, light maps, hdr
- Front end : user menu, UI
- Animation : Skeletal character animation
- Physics : collision, physical movement
- Scripts
- Network
- Audio

Low Level Renderer - OpenGL library
OpenGL : Low level renderer를 implement 하는데 사용하는 graphics rendering api. directX, vulkan 등등과 같은 한 종류.

geometry는 CPU에서 triangle mesh로 이루어지며 GPU는 mesh의 각 노드를 각각 병렬 처리하여 (per vertex operation) 위치(transformation)와 움직임, color(lighting)를 계산한다. 이후 Rasterization을 통해 triangle mesh를 pixel로 변환시킨다. 각 pixel를 이루는 fragment를 texture color와 lighting color를 구성하여 출력하면 이미지를 얻을 수 있다. (per fragment operation)

-> triangle mesh = geometry primitive
-> pixel = image primitive
이 서로 다른 파이프라인은 texture mapping을 통해 연결된다.

Game loop(GLUT in OpenGL)
User input -> Event handling(resize, collision, move) -> idle(AI, animation) -> render .... (loop)
각 한 번의 반복마다 하나의 이미지를 생성한다. 이 이미지를 frame이라 한다.
이들을 구현할 때 사용하는 함수를 callback-function이라 한다.
Frame Buffer (FB)
각 프레임은 frame buffer에 담겨 출력되므로 새로운 것을 출력하려면 이전 것을 지워야 한다.(glClear) 하나의 프레임 버퍼만 있다면 rendering refresh rate과 출력의 refresh rate가 서로 달라 flickering이 나타나게 된다. 그래서 하나의 프레임 버퍼를 더 추가하여 (front/back) 렌더링이 다되면 스왑하는 형식으로 프레임을 출력한다. 이를 double buffering이라 한다. (glutSwapBuffers)

Idle Callbacks
animation, continuous update를 할 때 사용하는 callback function
이는 움직이는 오브젝트를 프레임 마다 일정한 값만큼 계속 업데이트하여 움직임을 표현하는 방법이다.

Geometry primitives = geometry + connectivity
point, line, triangle_strip(한변을 공유하는 삼각형), line_loop(다각형) 등등 존재. (line_loop와 quad의 다른 점은 내부 색칠 여부, 다각형은 내부 색칠 가능)
알맞은 것을 선택하고 vertex 좌표를 입력하면 원하는 도형을 그릴 수 있다.
(각 vertex 정보가 저장되어 있으므로 원하는 vertex를 묶어 도형을 렌더링 가능)

View Systems
Rendering을 하여도 결국 플레이어가 보는 것은 camera를 통해 나타나는 scene이다. 따라서 scene이 사영되는 viewplane과 viewpoint에 의해 실제 렌더링을 사용자가 어떻게 보는지 결정된다.

- projection
- viewing /modeling / viewpoint transformation (based on the world coordinate system)
*model space - world space : 각 모델링의 스케일/좌표와 이들을 배치할 실제 게임 내 공간의 좌표. 각각을 world에 배치할 때는 transformation matrix를 곱하여 각각의 vertex위치를 결정하고, 스케일링하게 되며 이를 modeling transformation이라 한다.
마찬가지로 해당 world space와 배치된 모델링들을 view space로 옮기고,  plane으로 사영하기 위해서 또다시 transformation matrix를 곱해주면 최종적으로 원하는 화면에 오브젝트들이 배치되게 된다. (model의 공간 -> world 공간 -> view 공간 -> view plane으로 총 3번의 transformation)

이렇게 viewplane에 projection 된 것을 기반으로 이미지 렌더링을 하면 2d이미지이므로 frame화 하기 쉬워진다. 또한 이러한 과정은 각 vertex마다 matrix를 곱해주는 병렬 과정이므로 gpu의 병렬처리가 효과적이다.

이 과정은 수학적으로 하나의 좌표를 다른 좌표계로 매핑하는 것과 동일하며, V' = M*V 의 transform matrix calculation으로 나타낼 수 있다. (transformation 개수에 따라 여러 개의 matrix가 추가 가능)

여기에 더해 유저가 보는 화면은 렌더링 뿐 아니라 메뉴창, 컨트롤 옵션 등 다양한 부분이 포함될 수 있으므로 화면에 출력할 때 2d로 다시한번 리사이징을 거치게 된다. (viewport transformation)

3D Transformation - homogenous coordinates
vertex는 4*4 matrix가 곱해져 transformation되게 된다. (3*3은 scale/rotation, 3*1은 translate, 맨 밑 row는 [0 0 0 1]로 구성)

Projection transformation
- perspective projection : 카메라에 가까울 수록 크게 사영되는 일반적인 방법(fovy = field of view in y-axis, aspect = width / height ratio)
* 출력 윈도우 창의 크기가 달라지면 fovy와 aspect가 달라져야 원하는 크기로 출력될 수 있다. (아니면 오브젝트들이 더 작아지거나 크게 출력 될 수 있다)
- Orthographic parallel projection : 탑뷰, 사이드 뷰 같은 2D 게임에서 오브젝트들이 모두 같은 높이에서 평행하게 사영되는 방법. (평행하게 사영되므로 카메라와의 거리는 크기를 결정하지 못하지만 어느 것이 위에 오는지 아래에 오는지 결정하게 됨)

Viewing Transformation
gluLookAt(eye, aim, up) : 각각은 [x y z]로 구성되며 eye는 카메라의 위치, aim은 카메라가 보고 있는 방향, up는 aim과 수직인 방향(unique orientation)을 가리킨다.
이를 통해 world space가 viewing space로 구현될 좌표를 구성되는데, z축은 (aim-eye), y축은 up, 그리고 x축은 y와 z의 cross product로 계산하여 카메라의 좌표계를 만들 수 있다.


댓글

이 블로그의 인기 게시물

IIKH Class from Timothy Budd's introduction to OOP

Compiler 9 - Efficient Code generation

Software Engineering 10 - V&V, SOLID principle