본문 바로가기
게임개발뜯어보기

잉크 폭탄 얼룩은 스티커가 아닙니다 - 렌더 타깃과 시드

by 조생 2026. 9. 27.

폭탄이 터지면서 바닥이 확 칠해집니다. 얼룩은 매번 모양이 다르고, 화면 위 퍼센트는 실시간으로 오릅니다. 이 얼룩은 땅에 붙인 스티커가 아니라, 땅이 들고 있는 그림 한 장에 찍은 도장입니다. 그 칠하기를 언리얼 엔진에 직접 짜서 재 봤습니다.

영상판 — 방과 폭탄, 얼룩, 퍼센트는 전부 언리얼 엔진에 직접 짠 촬영 리그(C++)입니다. 게임 화면을 가져온 것이 아닙니다.

그림 1 — 얼룩 한 번(리그 식을 평면에 옮긴 도식): 겹친 가운데와 손가락, 튄 방울이 찍히고, 방울의 각도·거리·크기·회전은 모두 시드 하나에서 나옵니다

왜 이런 게 생겼나

닌텐도의 Splatoon 3 제품 페이지는 한 대전 모드를 팀의 잉크 색으로 가장 많은 땅을 덮기 위한 싸움이라고 적습니다. 칠한 넓이를 겨루는 게임에서 잉크는 그림이면서 동시에 데이터여야 합니다. 예쁘게 보여야 하고, 얼마나 칠했는지 셀 수 있어야 합니다.

덧붙이는 그림 조각, 즉 데칼(스티커)은 둘 중 보이는 일만 잘합니다. 그리기용 물체라 개수에 약하고, 얼마나 덮였는지 세려면 결국 따로 계산해야 합니다. 반면 표면마다 텍스처를 한 장 두고 거기에 찍으면 그리기와 세기와 발밑 판정이 한 자료에서 끝납니다.

첫째, 땅이 그림을 한 장 들고 있다

바닥과 벽, 그리고 상자의 면마다 그 그림 한 장, 즉 렌더 타깃(코드가 그려 넣을 수 있는 텍스처)을 붙입니다. 표면의 재질은 자기 월드 좌표를 정해진 축으로 투영해 그림 좌표를 만들고, 그 자리의 색을 읽어 기본 색과 팀 색을 섞습니다(그림 2). 젖은 곳은 거칠기를 낮춰 번들거리게 합니다.

그림 2 — 땅이 든 그림 한 장(리그 식을 평면에 옮긴 도식): 왼쪽 그림에는 주황 팀이 빨강 채널, 파랑 팀이 초록 채널로 찍히고, 오른쪽은 재질이 이 값으로 바탕색과 팀 색을 섞은 표면 색입니다

메시의 UV 대신 월드 좌표를 투영한 것은, 리그가 방울을 찍을 자리를 계산하는 식과 재질이 읽는 식이 반드시 같아야 하기 때문입니다. 메시 UV는 도구마다 달라 믿기 어렵고, 같은 식을 양쪽에 박아 두면 어긋날 일이 없습니다.

방울이 어디에 닿는지는 터진 자리에서 표면을 따라 걸어서 찾습니다. 각도를 하나 정하고 그 방향으로 정해진 거리만큼 면 위를 나아갑니다. 상자가 길을 막으면 그 면으로 꺾어 타고 오르고, 상자 윗면에서 터졌다면 모서리에서 꺾어 옆면을 타고 내려옵니다. 그렇게 멈춘 자리에 도장을 찍으니 바닥과 상자의 얼룩이 모서리에서 끊기지 않고 이어집니다(그림 3의 오른쪽). 처음에 터진 자리에서 곧은 광선을 쏘았을 때는 상자 옆면이 광선이 출발한 높이까지만 젖고, 윗면에서 터진 얼룩은 모서리 밖 허공으로 빠져 옆면에 닿지 않았습니다(그림 3의 왼쪽).

그림 3 — 면을 따라 걷기(리그 식을 상자 단면에 옮긴 도식): 왼쪽의 옛 곧은 광선은 상자 옆면을 출발 높이까지만 적시고 윗면의 잉크를 모서리 밖 허공으로 보내지만, 오른쪽처럼 면을 따라 걸으면 옆면을 타고 오르고 모서리를 돌아 내려가 얼룩이 이어집니다

둘째, 한 번의 폭발은 도장 하나가 아니다

액체가 든 풍선이 바닥에서 터진 자국은 큰 동그라미에 점을 뿌린 모양이 아닙니다. 유체역학과 법의학의 혈흔 분석이 연구해 온 특징을 이렇게 옮겼습니다.

  • 가운데는 원이 아닙니다. 퍼져 나가던 액체의 테두리가 감속하면서 불안정해져 돌기 여럿으로 갈라집니다. 그래서 겹친 도장 여러 장으로 찍습니다.
  • 돌기에서 손가락이 방사로 뻗습니다. 광선을 따라 이어진 자국이고, 끝에서 갈라지거나 이웃끼리 합쳐집니다. 손가락 끝이 끊기면 그게 튄 방울입니다. 부딪친 방울의 손가락 무늬는 Thoroddsen과 Sakakibara(1998)가 연구했습니다.
  • 방울은 멀수록 작아집니다. 일찍 튄 것은 얇은 테두리에서 빠르고 낮게 날아가 멀리 떨어지고, 나중에 튄 것은 두꺼워진 테두리에서 느리게 나와 가까이 떨어집니다. 튄 방울의 크기와 속도 분포는 Advances in Aerodynamics(2021) 논문이 다룹니다. 우리 리그는 크기를 거리의 제곱근에 반비례하게 잡았습니다.
  • 방울 모양도 원이 아닙니다. 비스듬히 부딪친 방울은 타원으로 찍히고, 짧은 축과 긴 축의 비가 충돌각의 사인값입니다. 법의학에서 핏자국의 각도를 역산할 때 쓰는 관계입니다(참고 자료의 National Institute of Justice 보고서). 꼬리는 늘 날아가던 쪽, 곧 가운데의 반대쪽을 가리킵니다.
  • 마른 얼룩은 가장자리가 진합니다. 테두리가 바닥에 붙들리면서 안쪽 액체가 바깥으로 흘러 색소를 실어 나르기 때문입니다. 커피 자국이 테두리만 진한 것과 같은 이치라, 속은 옅은 붓으로, 테두리는 진한 붓으로 찍었습니다.

난수를 끄면 완벽한 동그라미 하나가 남습니다(그림 4, 그림 6의 난수 끔 칸). 물감이 아니라 도장 자국처럼 보입니다. 무작위가 사실적으로 보이게 만드는 게 아니라, 무작위가 없으면 즉시 가짜로 보입니다.

그림 4 — 난수를 끄면 완벽한 동그라미(왼쪽), 켜면 물감처럼 튄 얼룩(오른쪽)

셋째, 그런데 무작위면 곤란한 게 있다

칠한 넓이가 점수라면, 얼룩은 모든 컴퓨터에서 같아야 합니다. 내 화면에서는 저 구석까지 칠해졌는데 상대 화면에서는 안 칠해졌다면 점수가 갈립니다.

그래서 난수는 시드 하나로 굴립니다. 폭발마다 정수 하나를 정하고, 그 정수로 난수 발생기를 초기화한 다음 방울 수십 개의 각도와 거리와 크기와 회전을 순서대로 뽑습니다. 같은 정수면 같은 순서로 같은 값이 나오므로 같은 얼룩이 찍힙니다. 얼룩을 통째로 보내는 대신 시작값만 맞추고 같은 계산을 돌리니, 모양을 정하는 난수 쪽은 네트워크로 정수 하나만 주고받으면 됩니다.

우리 리그는 폭발마다 방울 값들의 해시를 로그로 남깁니다. 같은 시드로 두 번 찍은 해시는 같았고, 시드를 바꾸면 해시도 얼룩도 달라졌습니다(그림 6의 시드 1·시드 2 칸).

넷째, 퍼센트는 픽셀을 세서 구한다

얼마나 칠했는지는 그림의 픽셀을 세면 나옵니다. 팀마다 다른 채널에 찍어 두면(그림 2) 채널별로 세기만 하면 됩니다. 다만 그림을 읽어 오는 일 자체가 비쌉니다. 우리 무대에서 모든 표면을 한 번 세는 데 11.07 ms가 들었습니다. 그래서 매 프레임이 아니라 몇 프레임에 한 번 셉니다.

그리는 비용은 스티커 방식과 견줬습니다. 그림 방식은 얼룩이 몇 개든 표면 개수만큼의 텍스처를 읽을 뿐이라 비용이 고정됩니다. 우리 무대에서 한 프레임의 GPU 시간이 1.19 ms였습니다. 스티커 방식은 개수를 따라 올라가, 스티커가 1054개 쌓인 구간에서는 그림 방식의 1.32배가 됐습니다.

그림 5 — 한 프레임 GPU 시간(ms): 그림 방식은 고정이고, 스티커 방식은 스티커가 424개, 1054개로 쌓일수록 오릅니다

더 나아가려면

상자는 면마다 그림을 따로 들어 한 개에 다섯 장입니다. 평면 투영 하나로는 옆면이 늘어나 보여서 면마다 따로 투영했습니다. 곡면이나 복잡한 물체라면 메시 UV를 제대로 펴거나 세 방향 투영 같은 다른 방법이 필요합니다. 세기도 줄일 여지가 있습니다. 우리 리그는 그림을 원래 크기 그대로 읽었으니, 줄인 그림으로 세는 것이 다음 후보입니다. 잉크를 밟으면 빨라지거나 벽을 타고 오르는 판정은 같은 그림을 읽는 일이지만, 움직임 쪽 규칙이라 이번에는 다루지 않았습니다.

참고 자료

그림 6 — 우리 리그에서 찍은 얼룩: 시드 1과 시드 2(시드가 다르면 모양도 다르다), 난수 끔(동그라미), 두 팀