Hacker News

Rendering pretty sky in Around The World game

Around The World 게임의 하늘을 더 아름답게 렌더링하기

항해 탐험 게임 Around The World의 개발자가 Godot에서 구름의 다중 산란, 대기 산란, 수평선과 톤 매핑을 조정해 하늘을 다듬습니다. 직접 만든 Rust 광선 추적기로 기존 구름 조명 테이블의 한계를 확인하고, 행성과 달의 공전·자전을 엔진에서 모델링해 일출과 일몰을 계산합니다.

에디터 노트

이 글에서 가장 설득력 있는 개선은 다중 산란을 직접 구현해 기존 LUT와 비교한 대목입니다. 단순히 구름 색을 손본 것이 아니라 두께가 있는 구름의 밝기 분포가 달라지는 이유를 확인했고, 얇은 구름에서는 차이가 작다는 조건도 밝혔습니다. 반면 대기 산란의 연산 순서 변경은 결과가 나아졌어도 적분 단계를 늘리면 차이가 줄어들어야 한다는 예상과 맞지 않습니다. 개발자도 셰이더에 다른 문제가 남았을 가능성을 적었습니다. 댓글의 사진 색 보정 경험담은 빛의 색이 지역과 시간에 따라 달라진다는 점을 덧붙이지만, 게임 렌더링 설정을 검증하는 근거와는 구분됩니다. 여기서 제시한 해결책은 완성된 물리 모델이라기보다 렌더링 결과를 개선한 구현과 임시 보정이 함께 있는 과정입니다.

AI 요약

항해와 탐험을 다루는 게임 Around The World는 초기 개발 단계입니다. 개발자는 플레이테스트에서 바다와 하늘, 구름이 함께 보이는 장면이 만족스럽지 않아 Godot 셰이더와 조명 설정을 손봤습니다. 각 변경은 구름의 빛 반응과 대기 색, 게임 행성의 곡률, 장면 전체의 색 표현을 다룹니다.

구름의 다중 산란

이전 작업에서는 POV-Ray로 만든 룩업 테이블(LUT)을 사용했습니다. 빛의 입사각과 구름 밀도에 따라 구름 밖으로 산란되는 빛의 양을 기록한 표입니다. 개발자는 설정에서 샘플과 간격을 늘려도 구름 구체의 아래쪽이 밝아지지 않는 점을 보고, POV-Ray가 다중 산란을 계산하지 않는다고 의심했습니다.

이를 확인하려고 특정 상황만 처리하는 간단한 다중 스레드 재귀 Monte Carlo 광선 추적기를 Rust로 직접 작성했습니다. 균일한 밀도의 구형 구름 하나만 렌더링하는 코드지만, 비교 결과 POV-Ray가 다중 산란을 반영하지 않는다는 의심을 확인했습니다. 두 LUT의 축과 일부 매개변수가 달라 완전히 동일한 조건의 비교는 아니지만, 다중 산란을 계산하면 구름에서 나오는 빛이 더 고르게 분포하고 구름 전체가 밝아집니다.

얇은 구름은 빛이 여러 번 산란될 가능성이 낮아 두 결과의 차이가 작습니다. 밀도가 높은 구름에서는 차이가 두드러집니다. 새 LUT를 적용하자 이전에 금속처럼 보이던 인상이 사라지고 구름 밑면이 밝아졌으며 조명도 부드러워졌습니다.

하늘빛을 받는 구름

구름은 태양의 직사광뿐 아니라 하늘에서 오는 간접광도 받습니다. 개발자는 파란색 값을 고정으로 더하는 대신, 시간대에 따라 달라지는 하늘색이 구름에 반영되도록 Godot의 환경광 처리를 이용했습니다. Godot는 환경에서 가져온 복사휘도와 조사도 정보를 큐브맵 형태로 사용합니다. 개발자는 정확한 내부 동작은 파악하지 못했다고 밝히면서도, 확산 재질인 구름은 표면 법선 방향의 간접광을 샘플링할 것으로 예상했습니다.

구름 밑면의 법선은 아래쪽을 향하지만 실제 구름은 구름 내부에서 산란된 하늘빛을 받습니다. 셰이더에서 법선을 하늘 쪽으로 바꾸자 구름에 푸른 기운이 생기고 하늘과 자연스럽게 섞였습니다. 일몰 장면에서는 직사광이 주황색이고 간접 하늘빛은 푸른색이라 구름이 분홍색으로 보였습니다. 개발자는 이 색이 실제 일몰의 구름에 더 가까워 보인다고 설명합니다.

대기 산란과 수평선

태양이 머리 위에 있을 때도 지평선 부근의 하늘이 지나치게 노랗게 보이는 문제가 있었습니다. 개발자는 광선 행진(ray marching)에서 광선을 약화하는 아웃스캐터링과 빛을 더하는 인스캐터링의 순서를 바꿨습니다. 기존에는 각 구간에서 인스캐터링을 더한 뒤 아웃스캐터링으로 약화했습니다. 수정한 순서는 먼저 아웃스캐터링을 적용하고 그다음 인스캐터링을 더합니다. 결과는 더 나아졌지만, 이 차이는 수치 적분 단계 수를 늘리면 사라져야 하는 오차로 예상했는데 실제로는 그렇지 않았습니다. 개발자는 다른 문제가 남아 있을 수 있다고 밝혔습니다.

게임 행성은 지구보다 약 75배 작아 지구의 대기 밀도와 높이, 행성 크기 매개변수를 그대로 사용하면 실제 지평선과 셰이더의 하늘 지평선이 어긋납니다. 두 지평선 사이에서 대기 밀도가 행성 중심으로 갈수록 계속 커지는 것처럼 계산돼 특히 일출과 일몰 때 어두운 띠가 생겼습니다. 개발자는 전역 시선 벡터의 수직 성분에 작은 값을 더한 뒤 다시 정규화해 하늘을 아래로 당겼습니다. 수평선 부근에서 효과가 가장 크게 나타나 어두운 띠가 실제 지평선 뒤로 숨습니다.

톤 매핑과 천체 운동

HDR 렌더링은 1.0보다 큰 색 값을 표현하지만 일반 모니터에 표시하려면 이를 LDR 범위로 변환해야 합니다. 단순히 값을 제한하면 색이 과포화될 수 있어 톤 매핑을 적용합니다. 개발자는 Godot의 Reinhard 톤 매퍼는 너무 어둡고 ACES와 AgX는 색을 지나치게 빼는 것으로 판단해, 화이트 포인트 2.0의 Filmic을 선택했습니다. 구름이 부드러워지고 멀리서 자연스럽게 흐려졌습니다. Godot는 사진처럼 사실적인 렌더링에 6.0 이상의 화이트 포인트를 권하지만, 그 설정에서는 장면이 너무 어두웠다고 설명합니다. 톤 매퍼가 앞서 조정한 조명과 색에도 영향을 주므로 밝기와 조명을 다시 맞췄고, 하늘 밝기를 절반으로 줄였습니다.

위치와 계절에 따른 일출·일몰, 달의 움직임과 위상을 계산하기 위해 행성과 달을 엔진 안에서 공전하고 자전하는 천체 모형(orrery)으로 만들었습니다. 그런 다음 엔진이 행성 표면의 관측자 위치에서 천체가 보이는 방향을 계산하도록 했습니다. 이 모형은 하늘을 렌더링하는 데 쓰였고 디버깅 도구 역할도 했습니다.

Hacker News 반응

  • @hbrav — 게임 콘셉트가 정말 마음에 듭니다.
  • @embedding-shape — 수평과 수직으로 구름 사이를 이동하는 또 다른 게임으로 최근 출시된 Ace Combat 8이 있습니다. 게임 자체는 UE5를 쓰지만 구름은 완전히 직접 만든 볼류메트릭 구름처럼 보이며, 게임 안에서 날아다니거나 구름 사이를 지나갈 때 특히 멋집니다. 예시 링크를 첨부합니다. VR로 하면 하늘과 환경, 구름 전체의 공간감이 훨씬 잘 느껴져 게임이 더 놀랍습니다.
  • @kylecazar — 게임이 완성되면 꼭 해보고 싶습니다. 게임을 많이 하지는 않지만 최근 Steam에서 오픈월드 항해·탐험 게임을 찾아보고 있었습니다. 제가 찾던 게임 같네요. 신기한 우연입니다.
    • @jbattle — Sailwind를 재미있게 했습니다. 한번 해보세요. 몇 가지 배와 간단한 경제 시스템이 있고, 작은 배로 시작해 점점 큰 배로 넘어갑니다. 돛 조작도 간단하게나마 들어 있습니다. 좌우로 방향을 바꾸고 돛을 올리거나 내리는 것만으로 끝나지 않습니다. 돛이 여러 개인 배는 다루는 재미가 있지만 감당할 만합니다. 진행은 느린 편이지만 저는 20시간 정도 즐겁게 했습니다.
  • @jimmydoe — 정말 보석 같은 글입니다. 특히 구름에 관한 글이 좋았고 최근에는 Ten Skies도 봤습니다. 신기한 우연입니다.
  • @smugglerFlynn — 주변의 빛이 실제로 어떻게 작용하는지에 관한 이런 통찰은 현대 디지털 사진에서 아직 잘 알려지지 않았다는 점이 흥미롭습니다. Fujifilm 온라인 커뮤니티에서는 지금 필름 시뮬레이션이 인기를 끌고 있습니다. Fuji 카메라는 필름 느낌 시뮬레이션이나 화이트 밸런스 색 이동 등 여러 설정을 카메라 안에서 조정할 수 있습니다. 사진을 찍으면 카메라가 설정을 즉시 적용해 후처리를 많이 하지 않아도 됩니다. 지난 2~3년 동안 소셜 미디어에서 인기가 퍼지고 Fuji 카메라를 새로 사는 사람이 늘면서 ‘필름 레시피’도 빠르게 늘었습니다. 그런데 사람들은 서로 다른 지역에서 찍은 사진을 예시로 공유합니다. 레시피는 대개 고정된 색 이동과 톤 곡선에 불과합니다. 인기 레시피끼리 설정 차이가 한두 단계뿐인 경우도 많습니다. 사진이 크게 달라 보이는 이유는 설정이 아니라 사진을 찍은 곳의 빛입니다. 직사광은 대기를 더 많이 통과할수록 노랗게 변하므로 위도와 계절, 시간대에 따라 달라집니다. 그림자는 푸른 하늘빛을 받습니다. 한 사진 안에도 색이 다른 빛이 섞이므로 고정된 색 이동 하나로 모두 같은 방식으로 보정할 수 없습니다. 캘리포니아에서 멋져 보인 ‘Wes Anderson’ 레시피가 핀란드에서는 노랗고 탁해집니다. 사람들은 설정 탓을 하거나 다른 레시피를 사지만 실제로 따라 하려는 것은 태양빛과 대기 산란입니다.
  • @wyrdcurt — 고맙습니다. 저는 이 게임과 비슷한 점이 있는 게임을 만들고 있습니다. 적어도 바다 여행이 들어간다는 점에서 그렇습니다. 이번 주에 Godot에서 하늘 셰이더를 작업했고 구름은 아직 구현하지 않았습니다. 이 시리즈 글이 제 관심사와 잘 맞습니다. 바다와 파도 렌더링도 할 일 목록에 있습니다. 게임 자체도 흥미로워 보이고 해보고 싶습니다. “지구에서 탐험은 종종 끔찍한 착취와 폭력을 뜻했고 그 영향은 지금도 남아 있습니다. 하지만 이 게임은 그런 이야기가 아닙니다. 사람들이 서로에게 더 친절하게 행동했다면 어땠을지를 보여줍니다.” 이 콘셉트가 마음에 듭니다. 제가 만드는 세계는 그 반대에 가깝습니다. 현실 세계의 무모한 지구 착취가 어떤 결과로 이어지는지 보여주고, 폐허 속에서 더 나은 삶을 찾게 합니다. 접근 방식은 다르지만 우리 모두 절망적인 비관주의에 빠지는 대신 이 세계가 더 나아질 가능성을 상상하려는 것 같습니다. 이런 픽션이 더 필요합니다.
  • @shrx — 지구에서 하늘로 빛이 반사되기도 합니다. 예를 들면 물 위에서 그렇습니다.
  • @mikeaskew4 — 훌륭한 작업입니다!
  • @x______________ — 멋져 보입니다. 제 2D Godot 작업이 초라해 보이네요. 재미있는 점은 댓글 9개 중 2개가 답글을 “<end statement>”로 끝냈다는 겁니다. 신기한 우연이네요. 더 신기한 우연입니다.
  • @AceJohnny2 — 구름 렌더링에 관해 말하자면 2008년에 대학 동기가 실시간 사실적 구름 렌더링으로 논문을 썼습니다. 논문과 발표 슬라이드 링크를 첨부합니다. 저는 슬라이드 24에 나온 전달 위상 함수(transference phase function)를 그때 알게 됐습니다. 이 함수에는 반사 각도에서 두 개의 첨두가 나타나는데, 상대적으로 잘 알려지지 않은 Glory 무지개에 해당합니다. 이 방식이 오늘날 비디오 게임에서 쓰이는지는 모르겠습니다. 지도교수 Fabrice Neyret은 Shadertoy 커뮤니티에서 활발히 활동하는 사람으로도 알 수 있습니다.

원문: Frozen Fractal / 번역·요약: Trawling