← 뒤로    메인
English    ☾

그래픽 엔진 만들기
입력 2021.12.28. 18:19 · 수정 2021.12.30. 10:07 · 라이선스
라이선스


이번 가을학기가 시작할 때쯤 갑자기 컴퓨터 그래픽에 관심이 생겼다. 그리고자 하는 물체들이 삼각형 표면들로 표현되고 각각을 평면에 사영시켜 표시할 픽셀의 위치를 찾는다는 정도의 막연한 지식은 가지고 있었지만 사영에 필요한 기하학이나, 텍스쳐/조명 등에 대해서는 아는 것이 전혀 없었다. 그래서 이런 것들을 배워가면서 그래픽 엔진을 직접 만들기 위해 참고할 자료를 찾던 중, 아주 적합한 유튜브 튜토리얼이 눈에 띄었다. OpenGL과 같은 그래픽 라이브러리를 일체 사용하지 않고, 컴퓨터 화면에 대한 인터페이스라곤 개별 픽셀에 해당하는 문자를 특정 위치에 출력하는 함수 하나밖에 사용하지 않았다. 총 네 편으로 구성되어 기본적인 사영 기하학부터 텍스쳐까지 다루고 있었다. 내가 찾던 가이드와 완벽히 일치했지만 한 가지 문제점이 있었다. 픽셀을 출력하는 함수가 Windows의 콘솔 API에 속한, Windows에서만 작동하는 함수였던 것이다. 맥북을 사용하는 나는 이를 대체할 함수를 찾아야 했는데, XCode를 이용하면 비슷한 기능을 가진 콘솔 어플리케이션 개발이 가능할지도 몰랐다. 하지만 개강을 앞두고 새로운 개발 도구를 팔 자신이 없었기에 일단 진행을 멈추기로 했다.

그리고 학기가 끝난 이번주, 다시 개발에 착수했다. 오랜만에 자리에 앉으니 새로운 목표가 하나 생겼다. 이번에는 외부의 자료 중 어떤 것도 참고하지 않고, 이미 내가 가지고 있는 지식만을 총동원하여 그래픽 엔진을 만들어보자는 것이 그것이었다. 성능 최적화보다는 원리 이해가 우선이었으므로 생각을 빠르게 옮길 수 있는 파이썬을 사용하기로 했다. 픽셀 그리기는 그냥 콘솔 전체를 덮을 크기의 2차원 문자 배열을 생성, 조작하고 그걸 그대로 출력해내면 될 것이었다. 바로 코드를 써봤다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from time import sleep, time
 
class XY:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
WIDTH, HEIGHT = 100, 30
 
SCREEN_BASE = [[' ' for _ in range(WIDTH)] for _ in range(HEIGHT)]
 
SCREEN = SCREEN_BASE.copy()
 
def clear():
    SCREEN = SCREEN_BASE.copy()
 
def fill(xy):
    SCREEN[HEIGHT-1-xy.y][xy.x] = '▇'
 
def render(pixels):
    clear()
    for pixel in pixels: fill(pixel)
    output = ' '.join(''.join(col for col in row) for row in SCREEN)
    print(output)
 
for i in range(30):
    render([XY(3*i, i)])
    sleep(0.1)
    
cs

기본적인 좌표 클래스와 그리기 기능을 만들었다. 약 0.1초마다 한 프레임씩 업데이트 하며 기울기 1/3의 직선을 그려봤다.

콘솔에 직선 그리기

오케이. 약간의 문제점이 있다면 full block 유니코드를 썼음에도 픽셀의 너비와 높이가 달랐고, 줄간격이 존재했다. 나중에 생각하기로 하고 패스.

이제 삼각형을 정의하고, 각 꼭짓점을 표시할 픽셀의 위치를 계산할 차례였다. 일단 사영에 필요한 기하학을 생각해보자.

사영 기하학 추론 시도

뭔가 변환 행렬을 이용한 우아한 사영 방법이 있을 것만 같았지만 1학년 말에 들은 선형대수학개론은 잊은지 오래고(사실 그때라고 이해한 것도 아니었다), 새로 생각해낼 머리도 안됐다. 그래서 일단 카메라와 점의 좌표, 카메라와 화면 사이의 거리, 그리고 카메라의 시각과 틸트 각도를 정의할 벡터 두 개를 놓았다. c와 d를 연결하는 직선과 화면 평면의 교점을 구해서 화면 중앙으로부터의 픽셀의 거리를 구한 뒤, 중앙-픽셀을 잇는 벡터와 w를 이용하여 화면 오른쪽 방향에 대한 픽셀의 회전각을 구하면 될 것이었다. 과정이 많이 더러울 것 같았지만 원하는 걸 구할 수만 있다면야 상관없다.

어? 그런데 3차원에서의 직선의 방정식이 갑자기 생각이 안 난다. 아무것도 참고하지 말자는 처음의 다짐은 온데간데 없고 금세 생각하기가 귀찮아져 위키백과를 찾았다. 식을 보자마자 기억이 완전히 돌아왔지만, 이렇게 기초적인 것도 바로 떠올리지 못한 것은 좀 충격이었다. 역시 잘 사용하지 않는 지식의 퇴화 속도는 정말 무섭다. 결국 프로젝트를 재개한지 불과 몇 분만에 나의 위치를 깨닫고, 필요한 기하학부터 찬찬히 공부하기로 했다.

참고한 자료.

필기 1페이지
필기 2페이지
필기
필기
필기
필기

Quaternions, Interpolation and Animation

To be continued.


#CS #CG 


제 뉴스레터를 구독하시면 새 글이 올라왔을 때 이메일을 받아보실 수 있습니다.


다음글: 2022년 1월

이전글: 나의 로망, 로마


목록으로

© 2026 이건희