SNOWFLOW를 만들었다. 브라우저 기반의 WebGPU 그래픽 데모인데, 변형 가능한 눈, 대기 조명, 물 느낌의 마법, 그리고 스노우 서핑에 집중했다.
눈 표면은 발자국, 움직임, 마법에 실시간으로 반응한다. 파인 자국, 솟아오른 둑, 다져진 눈, 얼음, 그리고 서서히 다시 차오르는 흔적까지 구현했다. 절차적 지형 생성, 천 시뮬레이션, 동적 마법 조명, 파티클 효과, 3인칭 스노우 서핑 시스템도 포함했다.
Claude Code with Opus 5가 프로젝트의 처음부터 끝까지 다 해냈다. 아키텍처 설계, Babylon.js와 WGSL 시스템 작성, 성능 프로파일링, 스크린샷 기반의 반복 수정, 기술적 의사결정 문서화까지 전부 맡겼다. 기존 스타터 프로젝트 없이 오직 구현 명세서만 가지고 바닥부터 쌓아 올렸다.
저번에 만든 사막 데모보다 성능 훨씬 잘 나오는 듯.
지난번에 프롬프트 공유해달라는 사람이 많아서 여기 남긴다. 물론 이 프롬프트는 뼈대일 뿐이고, Opus를 계속 굴리려면 추가 프롬프트를 엄청나게 쏴야 했다는 점은 알아둬라.
BASE PROMPT
SNOWFLOW — 기술 데모 · 구현 명세서
너는 실시간 그래픽 기술 데모의 유일한 엔지니어이자 테크니컬 아티스트다. 처음부터 끝까지 전부 다 만들어라. 이 문서는 사양서이자 아트 디렉션, 그리고 검수 기준이다.
핵심 지침
시각적 퀄리티가 곧 제품이다. 게임 루프도 없고, 진행도 없고, UI 설계할 것도 없다. 플레이어는 이걸 로드해서 90초 동안 눈밭을 걷고, 마법 몇 번 쓰고, 언덕을 서핑하다가 "이거 AAA급인데?"라고 생각하거나 아니면 그냥 탭을 닫을 거다. 아래의 모든 내용은 오직 그 한 가지 판단을 위해 존재한다.
이 문서의 모든 내용보다 우선하는 두 가지 규칙:
이 명세서의 요구사항이 데모의 퀄리티를 높이는 데 방해가 된다면, 요구사항을 무시해라. DECISIONS.md에 한 줄로 이유를 적어두면 된다. 범위 변경, 기술 교체, 혹은 픽셀 값 못 하는 기능은 과감히 쳐낼 권한이 있다.
로우 폴리, 플랫 셰이딩, 텍스처 없음, 자리표시자(placeholder), 혹은 "인디 프로토타입" 느낌이 나는 건 전부 결함이다. 완성된 것처럼 보이지 않는다면, 어설프게 내놓지 말고 아예 프레임에서 잘라내라.
"작동한다"에서 멈추지 마라. 모든 프레임이 깔끔하고, 응집력 있고, 바로 출시해도 될 수준으로 보일 때 멈춰라.
Modern JavaScript (ES2023 modules). JSDoc types encouraged, no TypeScript build step required.
Engine
Babylon.js latest stable, WebGPU only
Bundler
Vite
Target
Chrome stable on Windows 11, RTX 5070 Ti, 2560×1440
Frame target
90 FPS sustained. 60 FPS floor.
Frame time
No frame exceeding median + 4 ms after the loading screen dismisses
폴백(fallback)은 없다. WebGL 경로도, 모바일 경로도, 기능 감지 분기도 없다. navigator.gpu가 없으면 그냥 텍스트 한 줄 띄우고 끝내라. 호환성 맞추느라 시간 낭비하지 마라.
에셋은 지형, 노이즈, 대부분의 마스크를 포함해 더 나은 결과나 제어가 가능하다면 절차적으로 생성해라. 직접 만든 데이터보다 나은 경우(Poly Haven HDRI, 눈/얼음 PBR 머티리얼 스캔, ambientCG 디테일 텍스처 등)에는 무료 CC0 에셋을 써라. 모든 건 리포지토리에 벤더링해라. 런타임에 CDN에서 가져오는 건 금지다. 모든 서드파티 에셋과 라이선스는 ASSETS.md에 기록해라.
시스템
2.1 지형
평평한 평면은 이 데모를 망치는 지름길이다. 눈밭은 실제 형태가 있어야 한다.
플레이어 중심으로 지오메트리 클립맵이나 중첩 링 LOD를 구축해서, 카메라 근처는 삼각형 밀도를 높이고 거리가 멀어질수록 낮아지게 해라. 기본 줌 상태에서 안쪽 링의 정점 간격은 대략 10cm 미만을 목표로 한다.
높낮이는 GPU에서 합성된 레이어드 절차적 노이즈로 구현한다. 수십 미터 단위의 거대한 언덕 형태, 미터 단위의 중간 규모 설벽과 바람에 의한 돌출부, 그리고 데시미터 단위의 사스트루기(sastrugi) 능선과 물결무늬가 필요하다. fBm 옥타브 스택 하나 던져놓고 끝내지 마라. 지형은 주풍(prevailing wind)에 의해 깎인 방향성 구조가 필요하다. 풍향을 인코딩하고, 중간 및 미세 레이어들이 그 방향을 따라 늘어나고 깎이도록 만들어라.
중간 거리에 실루엣과 규모감을 줄 수 있게 노출된 암석 노두나 빙붕을 조금만 배치해라. 눈이 위쪽 면에 자연스럽게 쌓이게 하고, 너무 많이 깔지 마라. 핵심은 "눈과 플레이어뿐"이라는 컨셉이니까, 얘네들은 그냥 지평선이 심심하지 않게 해주는 용도일 뿐이다.
원경에는 산맥을 넣고 대기 원근법을 강하게 적용해라. 멀리 있는 능선은 매트 프로젝션이나 저사양 임포스터 링으로 때워도 되는데, 절대로 평면처럼 보이면 안 된다.
2.2 눈 셰이딩
이 셰이더가 프로젝트에서 제일 중요한 코드다. 예산도 그만큼 넉넉히 잡아라.
Babylon ShaderMaterial, PBRCustomMaterial 플러그인, 혹은 그에 준하는 방식으로 커스텀 머티리얼을 짜라. NodeMaterial이나 raw 셰이더 코드를 써서 WGSL로 구현해라. 그냥 하얀색 알베도만 입힌 기본 PBR 머티리얼은 쓰지 마라.
필수 구현 사항:
다중 스케일 노멀. 타일링 스케일 세 개를 섞어서 디테일 노멀 맵을 만들고, 거리와 경사도에 따라 블렌딩해라. 여기에 변형 높이 맵(§2.3)에서 추출한 노멀을 더해라. 가파른 경사면에는 트라이플래너 매핑을 써라.
서브서피스 스캐터링(SSS). 눈은 반투명하다. 랩 디퓨즈(wrapped diffuse)에 백스캐터 항을 추가해라. 그림자 지거나 빛이 스치듯 닿는 부분은 그냥 어둡게 죽이지 말고, 은은한 청백색 내부 광원이 도는 느낌을 줘라. "눈처럼 보인다"는 느낌을 내는 데 이만한 게 없다.
시점 의존형 반짝임(Glinting). 고주파 노멀 변위로 절차적 반짝임을 만들어라. 좁은 스펙큘러 로브와 스치는 시야각에만 강하게 걸리도록 하고, TAA를 켰을 때 지글거리거나 튀지 않게 안정적인 해시를 써라. 너무 과하지 않게 해라. 반짝이처럼 보이면 반으로 줄이고, 그래도 과하면 또 반으로 줄여라.
압축, 습도, 얼음 상태를 별도 표면 상태로 관리해라. 밟히거나 마법을 맞은 눈은 더 밀도가 높고 알베도도 어두우며, 스펙큘러 반응은 쫀쫀하고 산란은 적어야 한다. 다시 언 얼음은 더 매끈하고 반사율이 높아야 한다. 이 정보는 지형 상태 버퍼(§2.3)에서 읽어와서 이동과 마법 효과가 공유하게 만들어라.
접촉 디테일. 발자국 가장자리는 깔끔하게 깎인 모양이 아니라, 미세한 오클루전과 덩어리진 질감이 느껴져야 한다.
2.3 지형 상태 및 변형
여기가 상호작용 시스템의 핵심이다. 모든 게 여기에 기록되고, 눈 셰이더는 이걸 읽어서 작동한다.
플레이어를 따라다니는 렌더 타겟을 60~100m 정도 유지해라. 변형 영역의 텍셀 크기가 약 2cm 정도 되도록 해상도를 충분히 확보해야 한다. 4096² R16F 타겟을 플레이어 이동에 맞춰 토로이달(toroidal) 방식으로 스크롤하는 게 적당한 시작점이다. 텍셀 경계에 맞춰 이동을 스냅(snap)시켜서 화면이 울렁거리는 현상을 막아라.
권장 채널 (상황에 맞춰 하나나 두 개의 타겟에 패킹):
함몰 깊이(Depression depth) — 표면이 얼마나 파였는지.
변위 질량(Displaced mass) — 파인 곳에서 밀려난 눈이 발자국 가장자리에 쌓이는 둑. 이거 빼먹지 마라.
압축, 습도, 얼음 — 셰이딩에 쓰이는 지속적인 표면 상태.
규칙:
변형은 지속적이고 누적되어야 한다. 매 프레임 브러시 스플랫을 타겟에 찍어서 기록해라. 과거 이벤트 리스트를 가지고 매번 다시 계산하지 마라.
시간이 지나면 서서히 차오르도록 완만한 확산 및 감쇠 패스를 적용해서, 발자국이 점점 뭉개지다가 결국 사라지게 해라. 60초 뒤에도 발자국이 선명하게 보이도록 튜닝해라.
지형 버텍스 변위는 함몰 깊이와 변위 질량 채널을 샘플링한다. 같은 데이터로 노멀을 다시 계산해서 조명과 그림자가 제대로 반응하게 해라. 발자국에 스스로 그림자가 안 생기면 그건 실패작이다.
플레이어 발, 눈 위를 미끄러지는 웨이크, 그리고 모든 마법이 이 버퍼에 기록되어야 한다. 이렇게 기록 경로를 공유해야 마법이 눈 위에 떠 있는 효과가 아니라, 눈 속에 박혀 있는 것처럼 느껴진다.
2.4 대기 및 조명
낮고 따뜻한 태양을 써서 그림자를 길게 뽑아라. PCSS 스타일의 소프트 필터링이 적용된 캐스케이드 섀도우 맵을 써라. 근거리 발자국 그림자가 선명하게 유지되도록 캐스케이드 분할을 튜닝해라.
태양 각도를 더 잘 조절하고 싶으면 고품질 HDRI나 물리 기반 하늘 모델을 써라. 주변광은 파란색 쪽으로 강하게 치우쳐야 한다. 차가운 그림자와 따뜻한 빛의 대비가 눈 렌더링의 핵심이다.
높이에 따라 감쇠되는 안개와 대기 원근법을 추가해라. 거리가 멀어질수록 대비가 눈에 띄게 줄어들어야 한다.
그라운드 블로우나 스핀드리프트 추가: 들판을 가로질러 낮게 깔리며 바람에 날리는 눈보라를 말함. 지형을 가리지 않으면서도 환경이 살아 움직이는 느낌을 줘야 함.
볼류메트릭 라이트 샤프트는 이미지 퀄리티를 확실하게 높여줄 때만 추가할 것. 과하지 않게 절제해서 써라.
주문은 빛을 내뿜음. 다이내믹 라이트는 최대 4~6개로 제한하고 반경도 좁게 잡아라. 눈 셰이더의 서브서피스 스캐터링(SSS)이 여기에 반응하게 해서, 주문이 닿는 눈 더미 안쪽까지 빛이 은은하게 퍼지도록 만들어야 함.
2.5 포스트 프로세싱
순서가 중요함. 추천하는 체인:
TAA → SSAO → 젖거나 얼어붙은 표면에만 스크린 스페이스 리플렉션 → 아주 절제된 피사계 심도 → 절제된 블룸 → ACES 또는 AgX 톤매핑 → 은은한 필름 그레인 → TAA 이후 샤프닝.
TAA는 반짝이는 효과나 얇은 지오메트리를 안정화하는 데 필수임. 모든 포스트 프로세싱 효과는 설정 오버레이에서 개별적으로 껐다 켰다 할 수 있어야 A/B 비교가 가능함. 눈 렌더링에서 가장 흔한 실수가 하이라이트가 하얗게 날아가는 거니까, 하이라이트 롤오프를 항상 체크해라.
2.6 캐릭터와 로브
캐릭터는 거의 내내 중간 거리에서 뒷모습만 보게 될 거임. 실루엣, 옷감, 셰이딩에 예산을 다 쏟아붓고 얼굴에는 거의 투자하지 마라.
후드가 달린 겹겹의 로브를 만들고, 깊은 카울, 긴 소매, 오버 맨틀, 길게 끌리는 밑단을 넣어라. 후드와 소매 끝에는 셸 기반의 털을 넣고, 20~40개 정도의 셸과 알파 테스트된 가닥을 사용해라.
밑단, 소매, 맨틀에는 옷감 시뮬레이션을 넣어라. 거리와 굽힘 제약 조건이 있는 GPU나 CPU Verlet 시뮬레이션이면 충분함. 이동 속도, 가속도, 바람 필드를 이용해 움직임을 제어해라. 눈 위를 서핑할 때 옷감이 뒤로 확 젖혀져야 함.
옷감 셰이딩은 직물 느낌이 나도록 광택이나 보풀, 이방성 반응을 넣고, 얇은 부분에는 서브서피스 스캐터링을 추가해라. 그냥 평범한 PBR 유전체 재질 쓰지 마라.
얼굴은 후드 아래 그림자에 가려지게 둬라. 똑같은 퀄리티로 완성할 수 없는 수준의 디테일한 얼굴 모델링은 하지 마라.
리깅이나 이동 애니메이션을 높은 수준으로 뽑아낼 자신이 없다면, 어설프게 움직이는 것보다 차라리 옷감 시뮬레이션과 절차적 애니메이션으로만 움직이는 캐릭터가 훨씬 낫다. 발은 미끄러지지 말고 지면에 딱 붙어야 함.
발을 내디딜 때마다 눈이 파이고 튀어 올라야 함. 이건 발이 닿는 타이밍에 맞춰 프레임 단위로 정확하게 구현해야 한다.
2.7 카메라와 컨트롤
액션 MMO 스타일의 3인칭 시점을 써라. 카메라를 캐릭터 바로 뒤가 아니라, 살짝 오프셋을 줘서 어깨 위쪽에 배치해라.
WASD 이동은 카메라가 바라보는 방향 기준임. 마우스로 시점을 돌리고, 휠로 부드럽게 줌인/줌아웃해라.
충돌은 없지만 속도 변화를 감지하는 스프링 암 카메라를 써라. 가속할 때 살짝 뒤로 처지고, 속도가 붙으면 FOV가 넓어지고, 멈출 때는 다시 좁아져야 함. 모든 전환은 툭 끊기지 말고 부드럽게 이어져야 한다.
강력한 주문을 쓰거나 서핑 중에 급커브를 돌 때는 카메라를 살짝 흔들어줘라. 너무 과하지 않게.
2.8 주문: 1~5번 키
다섯 가지 주문 모두 하나의 '굽힘 문법'을 공유함: 끊김 없이, 관성을 유지하며, 자연스럽게 이어지는 흐름. 즉시 생성되거나 즉시 사라지는 건 없음. 모든 효과는 눈에서 서서히 나타나서 다시 눈 속으로 가라앉아야 함. 모든 주문은 지형 상태 버퍼를 읽고 써야 한다.
추천하는 구성 (더 좋은 결과물이 나온다면 수정 가능):
스윕(Sweep) — 전방 지면에서 진흙과 물이 초승달 모양으로 솟아올라 밖으로 퍼져나가며, 길을 파내고 양옆으로 흙더미를 쌓음.
리본(Ribbon) — 플레이어의 손과 카메라 조준점을 따라가는 지속적인 물줄기. 공중에 곡선과 8자 모양을 그리며, 그 아래 눈 위에 얇고 구불구불한 자국을 남김.
블룸(Bloom) — 타겟 지점에서 가루 눈과 물이 기둥처럼 솟구치며 분화구를 만들고, 가장자리가 솟아오른 뒤 천천히 반짝이는 가루가 되어 떨어짐.
크리스탈라이즈(Crystallize) — 물이 순식간에 얼어붙음. 서브서피스 스캐터링과 내부 빛 반사가 보이는 수정 결정체가 눈 더미에서 자라나며, 지면을 영구적으로 매끄러운 얼음 상태로 바꿈. 이 효과는 플레이어가 잠시 멈춰서 구경하게 만들 정도로 예뻐야 함.
Vortex — 플레이어 주변으로 눈보라가 소용돌이치며 지면의 눈을 눈에 띄게 걷어냄. 변형 버퍼(deformation buffer)가 고리 모양으로 얇아지면서 걷어낸 눈을 공중에 띄웠다가 다시 가라앉히는 방식임.
구현 방향: 응집력 있는 물체는 스플라인이나 파티클 스파인에서 GPU로 업데이트되는 스윕 방식의 프로시저럴 리본이나 튜브 메시를 쓰고, 스프레이, 안개, 물방울은 GPU 컴퓨트 파티클을 활용하셈. 반투명 처리를 위해 굴절 패스도 넣고. 화면 공간 유체 렌더링은 프레임 타겟 맞추기엔 좀 무거울 것 같긴 한데, 예산 내에서 돌아가고 결과물 퀄리티가 확실히 좋아진다면 써도 됨.
물 셰이딩 요구사항:
굴절은 색수차를 적당히 억제할 것.
깊이 기반의 흡수 틴트 적용.
애니메이션 흐름 맵 노멀.
선단부에는 거품과 슬러시 효과.
물방울이 튈 때는 모션 블러 스트리킹을 제대로 넣을 것.
2.9 Snow-surf: RMB(우클릭) 유지
이게 다른 모든 기능 합친 것보다 더 많이 쓰일 거임. 그러니까 제일 공들여서 다듬어야 함.
우클릭을 유지하면 플레이어 발밑으로 압축된 눈의 능선이 솟아오름. 플레이어는 가속하고, 마우스 움직임에 따라 몸을 기울이고 카메라가 뱅킹되면서 카빙 턴이 들어감.
핵심은 웨이크(wake)임. 턴 바깥쪽으로 눈이 밀려나면서 말려 올라가고 부서지는 파도 모양의 자국이 남아야 함. 이때 햇빛을 받아 반짝이고 그림자까지 드리우는 스프레이 기둥이 솟구쳐야 함. 스노보드 카빙이랑 보트가 지나간 자리를 적절히 섞은 느낌이어야 함.
Snow-surf는 지형 버퍼에 높은 둑(berm)을 만들면서 깊고 지속적인 자국을 남김. 한 번 달리고 나면 필드 건너편에서도 그 자국이 보여야 함.
진입하고 나갈 때는 뚝뚝 끊기지 말고 부드럽게 이어져야 함. 망토는 뒤로 휘날리고, FOV는 넓어지고, 화면 공간에는 바람 궤적이 나타나야 함. 오디오가 없으니까 시각적인 요소 하나하나가 속도감을 만드는 데 기여해야 함.
고속으로 턴할 때는 묵직하고 아날로그적인 느낌이 나야 함. 그냥 돌아가기만 하면 되는 게 아니라, 느낌이 올 때까지 손으로 직접 튜닝하셈.
성능 엔지니어링
가비지 컬렉션이 주적임. 12ms짜리 가비지 컬렉션 멈춤 현상은 눈에 확 띄고 AAA급 게임의 인상을 순식간에 망쳐버림.
렌더 루프에서는 할당을 아예 하지 마셈. 프레임당 코드 내에서 new 쓰지 마셈. 모듈 스코프에서 Vector3, Matrix, Quaternion 인스턴스를 미리 할당해두고 재사용하셈.
핫 패스(hot path)에서 새로운 객체를 만드는 map, filter, reduce, spread 문법이나 구조 분해 할당 쓰지 마셈. 그냥 인덱스 기반 for 루프 쓰셈.
성능 오버레이용을 포함해서 프레임마다 문자열 만들지 마셈. 오버레이는 적당한 간격으로 업데이트하고 버퍼를 재사용하셈.
모든 일시적인 효과, 파티클 버스트, 데칼에는 객체 풀(object pool)을 쓰셈.
GPU 버퍼 업로드에는 미리 할당된 타입 배열(typed array)을 쓰셈. 새로 만들지 말고 그 안에 값을 쓰셈.
정적 콘텐츠에는 scene.freezeActiveMeshes(), mesh.freezeWorldMatrix(), material.freeze(), scene.blockMaterialDirtyMechanism을 적극적으로 활용하셈.
반복되는 모든 지오메트리에는 씬 인스턴스(thin instances)를 쓰셈.
크롬 성능 패널이랑 Babylon 인스펙터로 프로파일링하셈. 오버레이에는 단순히 FPS 카운터만 띄우지 말고 1% 하위 프레임 타임 그래프를 같이 띄우셈. 평균 FPS는 가장 중요한 멈춤 문제를 가려버림.
프레임 예산을 정하고 그걸 지키셈. 90 FPS 기준 총 예산은 11.1ms임. 지형, 눈 셰이딩, 그림자, VFX, 옷감, 포스트 프로세싱에 예산을 명확히 배분하셈. 시스템별 실제 측정 비용은 PERF.md에 기록해두고.
로딩 및 파이프라인 웜업
WebGPU 파이프라인 컴파일 렉은 진짜 심각한 위험 요소임. 플레이어가 스킬 4를 처음 쓸 때 셰이더가 컴파일되면 수백 밀리초 동안 화면이 멈춰버림.
로딩 화면이 사라지기 전에:
모든 텍스처, HDRI, 메시, 버퍼를 로드하고 디코딩하셈.
모든 스킬, 포스트 프로세스, 셰이더 순열을 포함한 모든 머티리얼과 파티클 시스템 파이프라인을 작은 오프스크린 타겟에 한 번씩 렌더링해서 강제로 컴파일하셈.
모든 렌더 타겟을 예열하고 각 컴퓨트 패스를 몇 프레임씩 돌리셈.
그다음에 페이드 인하셈.
4초 걸려도 깔끔하게 로딩되는 게, 즉시 뜨는데 뚝뚝 끊기는 것보다 백배 낫다. 로딩 화면은 좀 센스 있게 만들어라. 어차피 유저가 제일 먼저 보는 게 로딩 화면인데, 브라우저 기본 스타일 그대로 놔두면 진짜 없어 보인다.
UI
설정창이랑 성능 오버레이만 넣어라. F1이나 백틱 키로 껐다 켰다 하게 만들고, 평소엔 숨겨놔.
내용물:
프레임 타임 그래프 (1% low 포함).
드로우 콜이랑 폴리곤 수.
포스트 프로세싱이랑 주요 시스템별 개별 토글.
그래픽 프리셋.
태양 각도, 안개 밀도, 반짝임 강도, 변형 깊이, 리필 속도 등 실시간으로 조절해야 할 아트 파라미터 슬라이더.
이건 초반에 미리 만들어놔. 나중에 시간 엄청 아껴준다.
HUD, 크로스헤어, 스펠 바 같은 거 절대 넣지 마. 화면에 아무것도 띄우지 마라.
프로젝트 구조
이 구조 추천하는데, 필요하면 알아서 바꿔:
/src
/core 엔진 부트스트랩, 렌더 루프, 리소스 매니저, 풀링
/terrain 클립맵, 절차적 하이트필드, 변형 버퍼
/shaders WGSL
/character 컨트롤러, 로브 천, 쉘 퍼
/spells 주문별 모듈 1개 + 공유 벤딩 프리미티브
/vfx 파티클 시스템, 데칼, 스프레이
/post 포스트 프로세싱 체인
/ui 설정 오버레이
/assets 벤더 파일, ASSETS.md 포함 DECISIONS.md 이 가이드라인에서 벗어난 모든 내용 + 이유 PERF.md 시스템별 프레임 예산 측정치
마일스톤
마일스톤마다 1440p 스크린샷 찍어서 꼼꼼하게 검토하고 커밋해라.
기반 구축 — WebGPU 부트, Vite, 렌더 루프, 프레임 그래프가 포함된 설정 오버레이, 카메라, 그리고 플레이스홀더 평면 위에서 WASD 이동 구현.
지형 및 눈 셰이딩 — 클립맵, 절차적 하이트필드, 서브서피스 스캐터링이랑 반짝임이 들어간 완벽한 눈 재질, 태양, 캐스케이드 섀도우, 하늘 IBL, 안개. 통과 기준: 캐릭터 없이 지형 스크린샷만 봐도 때깔 나고 분위기 쩔어서 바로 출시해도 될 수준이어야 함. 이 수준 안 나오면 절대 다음 단계로 넘어가지 마.
변형 — 전체 지형 상태 버퍼, 발자국에 따른 지형 변형, 리필, 정확한 노멀, 셀프 섀도우. 통과 기준: 발자국이랑 흔적이 지형을 확실히 밀어내고, 둔덕이 생기며, 조명이랑 자연스럽게 어우러져야 함.
캐릭터 — 로브, 천 시뮬레이션, 쉘 퍼, 이동, 발 디딤, 발자국 찍힐 때 튀는 눈 가루.
스노우 서핑 — 핵심이다. 여기엔 시간 아끼지 말고 쏟아부어라.
주문 — 주문 5개 전부 구현, 각각 지형에 흔적 남겨야 함.
포스트 프로세싱 및 폴리싱 — 전체 체인, 톤매핑 보정, 눈보라, 절제된 빛줄기 효과.
성능 최적화 — 프로파일링 돌려서 루프 내 모든 할당 제거하고, 90 FPS 유지하면서 1% low 60 FPS 넘기는지 확인해. 웜업 때 모든 파이프라인 다 돌아가는지도 체크하고.
시각적 합격 기준
데모 완성했다고 하기 전에, 1440p 스크린샷이랑 실제 움직이는 화면으로 다음 항목들 다 확인해:
화면에 각진 부분, 폴리곤 경계선, 평면 셰이딩 티 나는 곳 하나도 없어야 함.
눈 하이라이트가 완전 흰색으로 날아가면 안 됨. 그림자는 회색이나 검은색이 아니라 푸른빛이 돌아야 함.
멀리 있는 지형은 대기 원근감이 확실하고 명암 대비가 적절해야 함.
모래 언덕, 잔물결, 입자감 이렇게 세 가지 스케일의 지형 디테일이 동시에 다 보여야 함.
발자국 흔적에 둔덕이 생기고, 그림자가 제대로 지며, 시간이 지나면 자연스럽게 뭉개져야 함.
반짝임은 비스듬한 각도에서만 보여야 하고, 움직일 때 지글거리거나 튀면 안 됨.
로브는 겹겹이 쌓인 천 느낌이 나야 하고, 천 움직임이랑 털 질감이 제대로 살아야 함.
주문으로 생기는 물은 반투명하고 굴절되어야 하며, 내부 빛 산란이 보여야 함.
주문에서 나오는 빛은 닿는 눈을 확실하게 비춰야 함 (산란 포함).
모든 주문은 효과가 끝난 뒤에도 지형에 흔적을 남겨야 함.
스노우 서핑할 때 생기는 파동은 단순히 파티클 뿌리는 게 아니라, 질량이 밀려나면서 생기는 관성이 느껴져야 함.
데모는 90 FPS를 유지해야 하고, 1% low는 60 FPS 이상이어야 함.
주문을 처음 시전할 때 뚝 끊기는 현상이 없어야 함.
작업 방식
테스트 루프 돌리지 말고 그냥 만들어. 마일스톤마다 스크린샷 찍고 치명적인 버그 잡는 용도로만 Playwright 써라. 테스트 스위트 같은 거 짜지 마. 테스트에 쏟는 시간만큼 눈 셰이더 퀄리티만 떨어진다.
네 결과물을 끊임없이 확인해라. 스크린샷을 찍고, 꼼꼼하게 뜯어보고, 값을 계속 조정해. "프로토타입"과 "AAA급" 사이의 퀄리티 차이는 대부분 파라미터 튜닝에서 나오는데, 이건 직접 눈으로 확인하는 방법밖엔 없다.
보기 흉한 결과물을 그대로 둔 채 다음 단계로 넘어가지 마라. 특히 마일스톤 2는 확실하게 통과해야 하는 관문이다.
어떤 기술이 제대로 안 먹히면, 땜질하지 말고 그냥 바꿔버려라. 접근 방식은 네 마음대로 정해도 된다.