본문 바로가기

블로그 / 기술

640×360을 버리고 창 크기로 그리기: Salmonholic 화면을 선명하게 바꾼 0.13.0

작은 버퍼에 그린 뒤 통째로 늘리던 Salmonholic 렌더링을 창 해상도로 직접 그리게 바꾼 기록. 무제한 고해상도를 버린 이유와 해상도 상한, 같은 전투 프레임으로 비교한 전후 수치를 정리했다.

Salmonholic ·· 7분 읽기

같은 전투 프레임의 고양이 주변을 4배로 키운 비교. 왼쪽은 640×360에서 늘린 화면이라 YOU 글자가 깨지고, 오른쪽은 창 해상도로 그려 글자와 윤곽이 또렷하다

Salmonholic은 처음부터 640×360 화면을 기준으로 만들었다. 고양이, 연어, 초밥 모두 이 크기에서 보기 좋게 그렸고, 창이 크면 그 화면을 통째로 늘렸다. 픽셀아트 게임에서 흔한 방식이다. 그런데 9월 24일 무렵 화면을 다시 보니 글자가 문제였다. 고양이 머리 위의 “YOU” 표시는 아래쪽이 잘려 보였고, 체력 숫자는 가장자리가 계단처럼 뭉개졌다.

9월 25일 아침 0.13.0(커밋 68f1a08)에서 렌더링 방식을 바꿨다. 640×360 버퍼를 없애고, 같은 논리 좌표를 창 해상도에 직접 그리게 했다. 이 글은 그 결정과 측정 기록이다.

무엇이 흐려지고 있었나

Godot에는 화면을 늘리는 방법이 두 가지 있다. 기존 설정은 viewport 모드였다. 장면 전체를 먼저 640×360 텍스처에 그린 뒤 그 텍스처를 창 크기로 늘린다. 스프라이트든 글자든 일단 작은 버퍼에서 픽셀로 굳고, 그 상태로 커진다. 작은 글자의 세부는 이 단계에서 이미 사라진다.

창 크기가 640의 정수배가 아니면 더 나빠진다. 마지막 확대에서 어떤 픽셀은 두 칸, 어떤 픽셀은 세 칸이 된다. 같은 선이 자리마다 두께가 달라 보인다.

다른 하나는 canvas_items 모드다. 논리 좌표는 640×360 그대로 두고, 그리는 순간에 창 해상도로 바로 그린다. 바뀐 설정은 두 줄이다.

window/stretch/mode="canvas_items"     # 이전: "viewport"
window/stretch/scale_mode="fractional" # 이전: "integer"

배치 계산은 여전히 640×360 기준이라 HUD 위치나 화면비는 바뀌지 않는다. 바뀌는 것은 글자와 도형을 실제 화면 픽셀로 그린다는 점뿐이다.

세 후보를 같은 프레임으로 비교했다

바로 바꾸지 않고 후보 셋을 같은 조건에서 찍었다. 시드 7, 고정 60Hz로 오프라인 경기를 돌리고, 경기 15초 프레임에서 멈춰 화면을 저장했다. 화면 크기와 배율(DPR)을 바꿔 가며 11가지 조건을 찍었는데, 11조건 모두 전후의 전투 상태 문자열이 같았다. 같은 순간을 비교했다는 뜻이다.

후보 관찰 판정
기존 viewport, 640×360 작은 버퍼에서 굳은 뒤 확대. 비정수 창에서 픽셀 폭이 불규칙 비교 기준
canvas_items + 기기 배율 전부 사용 글자와 작은 초밥 윤곽이 선명. 1920×1080·DPR 2면 버퍼가 3840×2160 탈락
canvas_items + 해상도 상한 + 정수 확대 선명함 유지, 버퍼 크기는 제한 채택

두 번째 후보는 그림만 보면 가장 좋았다. 문제는 비용이었다. 고밀도 데스크톱에서 연어를 3배로 뿌리는 최대 부하를 걸자 프레임 95백분위가 CPU 18.70ms, GPU 65.53ms가 나왔다. 60fps의 한 프레임은 16.7ms다. 화면이 선명해지는 대신 게임이 끊기면 의미가 없다.

같은 프레임의 고양이를 4배로 확대한 비교. 왼쪽은 640×360에서 늘린 것, 오른쪽은 1280×720에 바로 그린 것 1280×720 원본에서 같은 사각형을 잘라 4배 확대했다. 왼쪽이 이전, 오른쪽이 0.13.0이다. 몸 윤곽과 둘레의 원이 덜 울퉁불퉁하다.

그래서 상한을 걸었다. 데스크톱은 버퍼를 최대 1920×1080, 휴대폰은 최대 1280×720으로 둔다. 상한보다 큰 화면은 정수배로 늘려 물리 픽셀에 맞춘다. DPR 2 데스크톱은 CSS 해상도로 그리고 2배로 붙인다. 844×390 크기에 DPR 3인 폰은 1266×585로 그리고 2배로 붙인다.

640×360을 중간 텍스처로 남기고 확대만 부드럽게 하는 방법도 따져 봤다. 하지만 창 해상도 렌더링이 제대로 돌아가는 이상, 이미 잃은 세부를 다시 늘리는 길을 하나 더 둘 이유가 없었다. 스프라이트는 최근접 필터를 그대로 쓰고, 화면 전체 후처리나 외곽선은 넣지 않았다.

성능은 오히려 좋아졌다

최대 부하(10인, 연어 생성 3배)로 20초씩 돌려 첫 3초를 빼고 조건마다 1,021프레임을 모았다. 모두 95백분위, 밀리초다.

조건 CPU 전→후 프레임 간격 전→후 GPU 전→후
1280×720 · DPR 1 9.70 → 7.60 25.20 → 18.20 18.47 → 16.41
1920×1080 · DPR 2 9.70 → 7.70 24.60 → 18.30 27.26 → 20.83
폰 844×390 · DPR 3 · CPU 4배 제한 34.10 → 32.10 34.70 → 34.30 20.32 → 13.98

드로 호출 최대치는 전후 모두 179회로 같았다. 숫자는 줄었지만, 나는 이 감소폭 전부를 코드 효과로 적지 않았다. 같은 머신에서 다른 작업도 돌고 있어서 측정마다 흔들림이 있었다. 판정 기준은 “15% 넘게 나빠진 조건이 없다”였고, 세 조건 모두 통과했다.

측정 자체에서 배운 것도 있다. 처음 헤드리스 성능 측정을 웹 빌드 수출, 브라우저 캡처와 동시에 돌렸더니 p95가 4.46ms에서 17.23ms로 튀었다. 네 배 가까이 나빠진 것처럼 보였다. 다른 작업을 모두 끝내고 이전 코드와 새 코드를 순서대로 다시 재자 5.37ms → 4.90ms였다. 두 실행 모두 연어 처치가 36,832회로 같아서 같은 시뮬레이션을 비교했다는 것도 확인했다.

체력과 레벨 글자를 4배로 확대한 비교. 위는 이전, 아래는 0.13.0 위가 이전, 아래가 0.13.0이다. 1280×720 DPR 1처럼 640의 정확한 2배인 화면에서도 숫자 곡선과 슬래시 가장자리가 더 매끈하다.

게임 결과는 한 글자도 바뀌지 않았다

렌더링만 바꾸는 작업이라 전투 시뮬레이션, 난수, 서버는 건드리지 않았다. 그래도 확인은 했다. 골든 테스트는 두 번 모두 경기 210.7초, 진화 42회로 기존 기록과 일치했다. 같은 900프레임에서 논리 화면 좌표의 차이는 RMS 0, 최대 0이었다. 게임 코드에서 바꾼 곳도 화면 배율을 정하는 함수 하나, 연습장 카메라에서 좌표를 정수로 반올림하던 부분 하나뿐이다. 나머지는 웹 페이지 쪽에서 캔버스의 화면 크기와 실제 버퍼 크기를 나눈 것이다.

같은 날 상한을 한 번 더 올렸다

0.13.0의 휴대폰 상한 720p는 오래가지 않았다. 한 시간 뒤 0.14.0(커밋 ab65fe5)에서 세로 플레이를 넣으면서 상한을 폰 2880×1440, 데스크톱 3200×2000으로 올렸고, 느린 폰은 프레임 간격을 보고 스스로 한 단계씩 낮추게 했다. 이 부분은 세로 화면 대응 글에서 자세히 다뤘다.

그다음 0.14.2(커밋 7d6481a)에서는 그림 쪽을 손봤다. 그때까지 고양이는 64px 칸 시트였다. 고양이 시트 40장을 원본 고해상도 소스에서 128px 칸으로 다시 뽑고, 1px 어두운 외곽선을 넣었다.

버전 커밋 바뀐 것
0.13.0 68f1a08 640×360 확대 → 창 해상도 직접 렌더링, 상한 1080p·720p
0.14.0 ab65fe5 상한 상향, 느린 폰은 4초 중앙값으로 한 단계씩 낮춤
0.14.2 7d6481a 고양이 시트 40장을 128px 칸으로 다시 제작

세 번의 배포는 모두 9월 25일 아침 8시부터 낮 12시 반 사이에 나갔다. 그리는 방식, 그리는 크기, 그려지는 그림 순서로 손댄 셈이다.

정리

작은 화면에 맞춰 만든 게임이라도, 그 작은 화면을 통째로 늘릴 필요는 없었다. 논리 좌표는 그대로 두고 그리는 해상도만 바꾸니 배치와 판정은 그대로였고 글자는 또렷해졌다. 다만 “가능한 한 크게”는 고밀도 화면에서 GPU 65ms라는 값을 냈다. 그래서 상한을 두고, 이후에는 프레임을 보고 스스로 낮추는 쪽으로 옮겨 갔다.

휴대폰에서 글자가 흐릿했던 이야기와 세로 화면 대응은 모바일 세로 화면과 터치 대응기에, 느린 기기에서 입자와 소리를 줄이는 장치는 적응형 품질 4단계에 따로 적었다. 웹 빌드의 다른 문제는 Godot 4 웹 export 기록에 있다. 바뀐 화면은 Salmonholic 게임 페이지에서 직접 볼 수 있다.

#Salmonholic#렌더링#해상도#Godot#픽셀아트#성능

함께 읽으면 좋은 글

전체 글 →