컴퓨터 그래픽스(Computer Graphics)의 정의
그래픽스 시스템에 대해서 전체적으로 알아봅니다. 컴퓨터 그래픽스라는 단어는 넓은 의미로 모호하게 사용되고 있습니다.
- 컴퓨터를 이용한 그래픽 디자인 또는 결과물 : 2D 포토샵, 일러스트레이터 등
- 컴퓨터를 이용한 애니메이션 또는 결과물 : 3D Max, Maya, Blender 등
- 컴퓨터 과학의 한 분야 : 컴퓨터를 이용해서 이미지 또는 애니메이션을 만들어내는 모든 기술
포스트에서는 3번의 정의를 따릅니다.
컴퓨터 그래픽스의 궁극적인 목표는 현실 세계를 시뮬레이션(Simulation) 하는데 목적이 있습니다.
먼저 실제 또는 가상의 물체를 시뮬레이션 합니다. 물체의 형태와 물성을 정의할 모델링 데이터가 필요합니다.
다음은 물체를 보려면 빛이 필요합니다. 그래서 빛의 동작을 시뮬레이션 합니다.
반사(Reflection), 굴절(Refraction), 회절(Diffraction)등 자연 현상에 대한 이해가 필요합니다. 이를 위한 물리학 또는 광학 같은 과학 법칙에 대한 시뮬레이션이 필요합니다.
마지막으로 빛을 받아들이고 처리하는 인간의 시각 또는 카메라를 시뮬레이션 합니다.
시뮬레이션 방법론은 물리학, 광학, 수학의 방정식(Equation)을 프로그래밍하여 구현합니다.
다만 개인용 컴퓨터의 사양에서 실시간(Realtime)으로 시뮬레이션 하기에는 연산 능력이 부족하기 때문에 적당한 근사(Approximation) 기법을 사용합니다.
이미지 생성(Image Synthesis)
현재의 컴퓨터 그래픽스에서 이미지를 생성하는 방식은 인간의 시각 또는 카메라에 보이는 것을 그대로 시뮬레이션 하고 있습니다.
그러다보니 현실과 시뮬레이션을 구성하는 요소들은 다음과 같은 대응관계가 성립합니다.
- 실세계(Real world) : 3차원 공간(3D Space)
- 실제 물체(Object) : 오브젝트(Object)
- 카메라(Camera) : 뷰어(Viewer)
고전 광학 이론을 가져와서 컴퓨터 상에서 광원(light Source), 반사, 굴절, 회절 등을 시뮬레이션 합니다.
다음은 빛을 처리하는 과정인 인간의 시각 시스템을 시뮬레이션 해야 되는데 시신경이 받아들인 정보를 토대로 뇌(Brain)가 후처리 과정을 거치기 때문에 이를 시뮬레이션하기 위해서는 고성능의 인공지능이 필요합니다. 따라서 실시간으로 시뮬레이션 하기에는 큰 무리가 있습니다.
그래서 컴퓨터 그래픽스에서는 인간의 시각 대신 카메라를 시뮬레이션 합니다.
카메라가 하는 일은 3차원 공간 상에 있는 물체를 카메라로 촬영하면 2차원 평면인 필름(Film)에 투영(Projection) 해줍니다. 따라서 카메라를 시뮬레이션해서 뷰어로 사용합니다.
실제 세계의 카메라 라고 하면 가장 먼저 SLR(Single Lens assembly Reflex camera) 카메라가 떠오를 것입니다.
SLR 카메라의 렌즈(Lens)는 단일 렌즈가 아닌 여러개의 볼록, 오목 렌즈가 복합적으로 기능하여 고품질의 이미지를 획득 하는 구조입니다.
SLR 카메라는 여러개의 렌즈를 시뮬레이션 해야 하기 때문에 필요한 연산량이 너무 많습니다. 그래서 더욱 시뮬레이션 하기 쉬운 카메라를 찾게 됩니다.
컴퓨터 그래픽스 분야에서 채택한 카메라는 바늘 구멍 사진기(Pinhole Camera) 입니다.
상자에 아주 작은 크기의 구멍을 통해 빛이 간신히 들어오게 하면 안쪽 상자에 부착한 반투명 유리에 상이 맺힌다는 간단한 원리입니다.
가장 간단한 구조의 카메라 라도 현실 세계의 상을 획득하는 것이 충분히 가능하기 때문에 바늘 구멍 사진기 모델으로부터 컴퓨터 그래픽스의 뷰어가 발전하게 됩니다.
합성 카메라 모델(Synthetic Camera Model)
바늘 구멍 카메라의 수학적 해석
바늘 구멍의 위치를 원점으로 3차원 직교 좌표계를 설정합니다.
일반적으로 바늘구멍이 있는 평면을 ${xy}$ 평면으로 설정하고 바늘구멍에서 물체를 바라보는 축을 ${z}$축으로 설정합니다.
원점 뒤 쪽에는 상이 맺히는 필름(바늘구멍 사진기의 유리)가 있고, 앞 쪽에는 물체가 있습니다.
원점을 기준으로 필름과 물체의 위치를 선으로 이어보면 두 개의 직각 삼각형이 만들어집니다.
물체를 가르키는 큰 삼각형과 상이 맺히는 필름을 가르키는 작은 삼각형입니다.
- ${z =}$ 원점에서 물체까지의 거리
- ${z_{p} =}$ 원점에서 필름까지의 거리
실제 물체의 위치 ${x}$는 필름의 위치 ${x_{p}}$에 대응되고
실제 물체의 위치 ${y}$는 필름의 위치 ${y_{p}}$에 대응됩니다.
${(x, y)}$ 를 이용하여 연립 방정식을 만들고 이를 계산하면 필름 상에서의 좌표 ${(x_{p}, y_{p})}$ 를 알 수 있습니다.
따라서 3차원 공간 상의 모든 위치에 대해서 정확하게 필름의 2차원 평면으로 맵핑(Mapping) 할 수 있습니다.
그러나 바늘 구멍 사진기에는 치명적인 약점이 하나 있습니다. 바늘 구멍인 원점 기준으로 필름이 원점보다 뒤 쪽에 있기 때문에 상이 맺힐 때 거꾸로 맺힙니다.
이를 해결하기 위하여 컴퓨터 계산 상에서는 뒤 쪽에 있는 필름을 앞 쪽으로 이동하여 계산합니다. 이는 컴퓨터 모니터(Monitor), 창문(Window) 같이 2차원 평면으로 생각할 수 있습니다.
이처럼 3차원 물체를 2차원 평면으로 가져오는 과정을 투영(Projection)이라고 합니다.
래스터 시스템(Raster System)
현대의 그래픽 카드(Graphic Card)들은 기본적으로 래스터 시스템으로 구현되어 있습니다.
그래픽 카드의 구조는 그래픽스 프로세싱 유닛(Graphics Processing Unit, 이하 GPU)와 GPU 메모리(Memory)로 구성되어 있고 GPU 메모리 중 일부는 프레임 버퍼(Framebuffer)라는 화면을 그대로 저장해두는 메모리 영역으로 사용합니다.
앞서 설명한 합성 카메라 모델을 시뮬레이션해서 만들어낸 이미지는 프레임 버퍼에 저장되며 이것을 그래픽 카드가 모니터에 출력하는 방식으로 작동합니다.
프레임 버퍼에 이미지를 저장하는 방식이 래스터 시스템입니다. 래스터 시스템의 핵심은 합성 카메라 모델로 시뮬레이션한 이미지를 2차원의 배열으로 저장하고 해석한다는 아이디어입니다.
2차원 배열의 원소들이 각자의 색상 정보가 있는 사각형인 픽셀(Pixel, Picture Element)입니다. 이런 픽셀들을 모아서 이미지를 형성할 수 있습니다. 픽셀의 크기를 매우 작게 설정하거나 멀리서 보여준다면 사람의 눈에는 부드럽게 이어진 그림처럼 보이게 됩니다.
또한 그래픽 카드는 프레임 버퍼에 저장한 이미지를 모니터에 연속적으로 출력하는 하드웨어 기능도 가지고 있습니다.
${1}$초에 몇 번이나 이미지를 연속해서 출력할 수 있는지 측정한 속도를 초당 프레임(Frame per Second)이라고 부릅니다.
현대의 GPU는 계산이 워낙 빠르기 때문에 모니터 하드웨어의 주사율(Refrash Rate)이 지원한다면 ${60}$ FPS, ${144}$ FPS 이상의 속도로 출력 할 수도 있습니다.
정리하자면 픽셀들을 모아서 저장하는 것을 래스터(Raster)라고 하며 모니터를 통해 출력할 픽셀을 저장한 것이 프레임 버퍼입니다.
그래픽 카드의 핵심은 프레임 버퍼에 픽셀을 저장하는 것입니다. OpenGL을 이용하여 그래픽 카드에 있는 GPU와 메모리를 사용해서 계산을 통해 프레임 버퍼에 저장된 픽셀을 변경(Update)하면 출력을 우리가 원하는 대로 바꿀 수 있습니다.
그래픽스 아키텍쳐(Graphic Architecture)
모델링-렌더링 패러다임(Modeling-Rendering Paradigm)
그래픽스 아키텍쳐가 발전한 순서대로 따라가보겠습니다. 가장 오래되었고 단순한 구조는 모델링-렌더링 패러다임입니다. 이는 래스터 시스템과는 상관없이 철저하게 컴퓨터 소프트웨어 관점에서 생각하는 구조입니다.
3DS MAX, MAYA, Blender 등의 DCC(Digital Create Contents) 제작 툴 소프트웨어를 통해 모델러(Modeler)가 3차원 모델링 데이터를 제작하고 이를 파일 포맷으로 저장하여 렌더러(Renderer)에 전달합니다.
Vray, Arnold, Renderman 등의 렌더링 소프트웨어를 통해 렌더러(Renderer)가 합성 카메라 모델을 시뮬레이션하여 전달 받은 3차원 모델링 데이터를 해석하여 실제로 모니터에 그려질 이미지를 계산하는 일을 합니다.
이 구조의 특징은 모델러와 렌더러의 역할을 서로 다른 소프트웨어로 철저히 분업하는 것이 기본적인 아이디어입니다. 이 구조는 영화와 CG에서 아주 많은 연산량이 필요한 높은 퀄리티의 이미지를 만들 때 사용하며 실시간 처리에는 사용하지 못합니다.
그래픽스 모델
실시간 처리를 지원하기 위해 다른 구조들이 발전합니다. 과거의 CPU만 있던 상황에서는 CPU 단독 처리 모델(Single CPU Model)이 있었습니다.
CPU가 모델링도 해주고 렌더링도 해주고 모니터에 출력까지 담당했으나 연산량이 너무 많이 필요해서 현재는 사용되지 않습니다.
그래서 그래픽스 연산만 전담하는 DPU(Display Processing Unit)를 추가한 DPU 모델으로 발전하였으며 이것이 그래픽 카드의 원시적인 형태입니다.
이후 반도체 기술이 획기적으로 발전하면서 파이프라인 모델(Pipeline Model)이 등장합니다.
기존에는 컴퓨터 소프트웨어에서 처리하던 그래픽스 연산을 물리적인 프로세서로 분리한 VLSI(Very-Large Scale Integrated circuits) 칩으로 설계하는 것입니다.
프로세서들을 단계별로 이어진 하드웨어 파이프라인으로 처리한다는 아이디어로 전체적으로 실시간 처리가 가능할 만큼 성능이 발전하게 됩니다.
프로그래머블 파이프라인 모델(Programable Pipeline Model)
이전에는 소프트웨어의 기능을 고정된 VLSI 칩으로 제작하였지만 대신 프로그래밍 가능한 프로세서(Processor)를 채택하고 필요한 소프트웨어를 프로세서에 설치하여 사용하면 더 효율적이고 범용적으로 응용 가능하다는 사실을 발견하게 됩니다.
파이프라인을 구성하는 칩들 중에서 일부를 프로그래밍 가능하고 고성능 병렬 처리가 가능한 그래픽스 프로세서 유닛(Graphics Processing Unit)으로 변경하고 이를 셰이더(Shader) 라고 부릅니다.
셰이더를 프로그래밍하기 위해서는 고수준(High-level) 프로그래밍 언어가 필요했기 때문에 셰이더 언어(Shader Language)가 탄생합니다. 여기에 별도의 컴파일러(Complier)도 필요하게 됩니다.
현재의 OpenGL과 셰이더 언어를 사용하는 프로그래머블 파이프라인 모델이 최신 그래픽 카드의 기본적인 구조가 됩니다.
GPU와 GPGPU(General Purpose GPU)
GPU의 특징은 그래픽스 연산을 실시간으로 처리해야 하기 때문에 부동 소수점과 행렬을 연산하는데 최적화되어 있고 이를 병렬 계산하는 구조입니다.
그래서 GPU의 엄청난 연산 성능을 다른 곳에도 응용할 수 있지 않을까 고민한 결과 GPGPU를 제작하게 됩니다. GPU를 일반적인 목적으로 CPU를 대신 계산에 사용 해보자는 시도였습니다.
이것이 성공하면서 대규모 병렬 컴퓨팅(MPC, Massively Parallel Computing) 분야가 시작됩니다. 현재의 OpenCL 이나 CUDA 등 대규모 병렬처리 기술들이 MPC를 기반으로 인공지능 구현과 같은 굉장히 복잡한 계산들이 가능해졌습니다.