유체·천·연체 시뮬레이션
강체는 위치 하나와 방향 하나면 상태가 끝나지만, 펄럭이는 망토와 출렁이는 젤리와 피어오르는 연기는 수천, 수백만 개의 값이 서로 밀고 당긴다. 질량-스프링에서 시작해 위치 기반 동역학(PBD, XPBD), 천과 머리카락, 연체와 소성, 나비에-스토크스와 격자 유체, SPH와 FLIP, 바다와 연기, GPU 병렬화, 그리고 게임이 이 모든 것을 속이는 방법까지 작은 시뮬레이션을 직접 돌린 그림으로 따라간다.
목차 (16)
강체 너머: 입자로 볼까, 격자로 볼까
강체 시뮬레이션은 물체 하나를 무게중심 위치, 방향(쿼터니언), 선속도, 각속도 열세 개 남짓한 숫자로 다룬다. 모양이 변하지 않는다는 가정 하나가 문제를 작게 만든다. 강체의 적분, 충돌 판정과 충격량 응답은 게임 물리학 노트에 있다. 이 노트는 그 가정을 버린다. 천은 모양이 매 순간 바뀌고, 물은 아예 정해진 모양이 없다. 그러면 "상태"를 무엇으로 적을지부터 다시 정해야 한다.
방법은 크게 둘이다. 라그랑주(Lagrangian) 표현은 물질 덩어리를 입자나 정점으로 쪼개 그 조각을 따라간다. 입자마다 위치, 속도, 질량을 싣고 다니므로 물질이 움직이는 것(이류)은 공짜다. 대신 "내 근처에 누가 있나"를 매번 찾아야 한다. 천의 정점, 머리카락의 마디, SPH 입자가 이쪽이다. 오일러(Eulerian) 표현은 공간을 고정된 격자로 나누고 각 칸에서 그 자리를 지나가는 속도, 밀도, 온도를 잰다. 이웃이 늘 정해져 있어 미분과 압력 풀이가 쉽지만, 물질이 칸 사이를 옮겨 가는 것을 따로 계산해야 하고 그 과정에서 값이 뭉개진다. 연기와 불, 격자 유체가 이쪽이다.
현대 기법의 상당수는 둘을 섞는다. FLIP과 MPM은 입자로 물질을 나르고 격자에서 압력과 힘을 푼다. 어느 쪽을 고르든 이 노트의 모든 방법은 결국 "많은 자유도를 작은 시간 간격으로 앞으로 밀어 가는" 문제이고, 무엇을 정확히 하고 무엇을 포기할지의 선택이다.
질량-스프링 계: 가장 단순한 변형체
변형체를 만드는 가장 직관적인 방법은 질점(작은 공)을 스프링으로 잇는 것이다. 스프링 하나는 쉬는 길이 L에서 벗어난 만큼 양 끝을 당기거나 민다. 힘은 훅의 법칙 F = −k(|xb − xa| − L)이고, 진동이 끝없이 이어지지 않게 두 점의 상대 속도에 비례하는 감쇠를 더한다. 매 걸음 모든 스프링의 힘을 더해 각 질점의 가속도를 구하고 적분하면 끝이다. 단진동과 감쇠의 물리는 물리학 노트에 있다.
천을 격자로 만들 때 스프링은 세 종류를 겹친다. 바로 옆 정점을 잇는 구조 스프링은 늘어남을, 대각선으로 잇는 전단 스프링은 마름모꼴로 찌그러지는 것을, 한 칸 건너뛰어 잇는 굽힘 스프링은 종이처럼 접히는 것을 막는다. 굽힘 스프링이 없으면 천이 아무 저항 없이 접혀 젖은 휴지처럼 보이고, 너무 세면 판지처럼 뻣뻣해진다.
질량-스프링은 만들기 쉽고 직관적이지만 약점이 둘 있다. 강성 k가 물리적 재료 상수와 바로 이어지지 않아(같은 천도 격자를 촘촘하게 하면 다르게 행동한다) 값을 손으로 맞춰야 하고, 무엇보다 단단한 스프링은 시간 간격을 아주 작게 강요한다. 다음 절이 그 이야기다.
강성과 시간 간격: 명시적, 반암시적, 암시적 적분
스프링 하나에 매달린 질점은 각진동수 ω = √(k/m)로 떨린다. 이를 시간 간격 dt로 나눠 계산할 때 적분 방식에 따라 결과가 갈린다. 명시적(앞으로) 오일러는 지금 속도로 위치를, 지금 힘으로 속도를 옮긴다. 이 방식은 감쇠 없는 진동에서 에너지가 걸음마다 정확히 (1 + ω²dt²)배로 늘어나므로 dt가 아무리 작아도 언젠가 터진다. 반암시적(심플렉틱) 오일러는 속도를 먼저 갱신하고 그 새 속도로 위치를 옮긴다. 순서만 바꿨는데 에너지가 늘지도 줄지도 않고 출렁이며 머문다. 단, dt가 2/ω를 넘으면 터진다. 적분 방식의 일반론은 계산 과학 노트와 게임 개발 › 물리의 적분 절에 있다.
문제는 천과 머리카락이 "늘어나지 않아야" 한다는 점이다. 거의 늘어나지 않게 하려면 k를 크게 해야 하고, k가 크면 ω가 커져 허용되는 dt가 줄어든다. 질량 0.01kg짜리 질점(천 1m²를 100개 정점으로 나눈 정도)으로 계산하면 다음과 같다. 이렇게 빠른 성분과 느린 성분이 섞여 가장 빠른 성분이 걸음 크기를 정해 버리는 상황을 강성(stiff) 문제라 부른다.
| 스프링 상수 k (N/m) | 허용 dt = 2√(m/k) | 60fps 한 프레임에 필요한 걸음 수 |
|---|---|---|
| 100 | 20.0ms | 1 |
| 10,000 | 2.0ms | 9 |
| 1,000,000 | 0.20ms | 84 |
암시적 적분: 큰 걸음과 그 대가
암시적(뒤로) 오일러는 "걸음이 끝났을 때의 힘"으로 속도를 고친다. 미래의 위치를 모르니 걸음마다 연립 방정식을 풀어야 하지만, 대신 dt를 아무리 크게 해도 터지지 않는다. Baraff와 Witkin의 Large Steps in Cloth Simulation(SIGGRAPH 1998)이 천에 암시적 적분과 켤레 기울기법을 써서 큰 걸음을 가능하게 한 대표적인 논문이고, 이후 많은 오프라인 천 시뮬레이터가 이 계열을 따랐다. 대가는 두 가지다. 걸음마다 큰 희소 행렬을 푸는 비용, 그리고 위 그림에서 보듯 에너지가 저절로 빠져나가는 수치 감쇠다. 큰 걸음일수록 천이 꿀 속에서 움직이는 것처럼 둔해진다.
위치 기반 동역학(PBD): 힘 대신 위치를 고친다
게임은 행렬을 풀 시간도, 작은 걸음을 수십 번 돌릴 시간도 없다. Müller 외의 Position Based Dynamics(VRIPHYS 2006)는 발상을 뒤집었다. 스프링 힘을 계산하지 않고, "이 두 점 사이 거리는 L이어야 한다" 같은 제약을 두고 위치를 직접 그 조건에 맞게 옮긴다. 이 생각의 뿌리는 Hitman: Codename 47에 쓰인 Jakobsen의 Advanced Character Physics(베를레 적분과 제약 반복)에 있다.
한 걸음은 세 단계다. ① 예측: 외력만 보고 위치를 먼저 옮긴다(p = x + dt·v + dt²·f/m). ② 제약 투영: 제약을 하나씩 돌며, 어긴 만큼 관련된 점들을 역질량 비율로 나눠 옮겨 그 제약만 정확히 만족시킨다. 하나를 고치면 옆 제약이 다시 어긋나므로 전체를 여러 바퀴(가우스-자이델 반복) 돈다. ③ 속도 갱신: v = (p − x)/dt로 위치 변화에서 속도를 거꾸로 얻는다. 위치가 늘 제약 근처에 머물기 때문에 폭발하지 않고, 충돌도 "바닥 아래로 내려가지 않는다"는 부등식 제약 하나로 끝난다.
시작: 점 0은 못에 박혀 있고(역질량 0), 점 1·2는 속도 0으로 수평에 놓여 있다. 두 마디의 쉬는 길이는 1이다.
대가는 강성이 반복 횟수와 시간 간격에 따라 바뀐다는 점이다. 반복을 적게 돌면 제약이 덜 만족되어 천이 고무처럼 늘어난다. 논문은 원하는 강성 k를 반복 ns번에 나눠 쓰도록 한 번 반복의 강성을 k' = 1 − (1 − k)1/ns로 보정하는 방법을 제시했다(예: k = 0.5, 반복 10번이면 k' = 0.067). 그래도 dt에 대한 의존은 남는다고 논문 스스로 적었다. 고정 시간 간격을 쓰는 게임에서는 크게 문제 되지 않았지만, 프레임마다 반복 횟수를 바꾸면 재질이 바뀐다.
XPBD: 반복 횟수와 상관없는 강성
Macklin, Müller, Chentanez의 XPBD(MIG 2016)는 PBD에 숫자 둘을 더해 이 문제를 풀었다. 제약마다 강성의 역수인 컴플라이언스 α와, 지금까지 그 제약이 낸 힘의 누적인 라그랑주 승수 λ를 둔다. 반복마다 고칠 양은 Δλ = (−C − α̃λ)/(∇C·M−1·∇CT + α̃), α̃ = α/dt²다. α = 0이면 원래 PBD와 같고(무한히 단단함), α가 크면 제약이 부드럽게 늘어난다. 이 식은 암시적 적분을 한 번의 국소 반복으로 풀어 가는 것과 같아서, 반복을 몇 번 돌든 수렴한 곳의 강성이 같다. 덤으로 λ가 제약에 걸린 힘을 알려 줘서 "힘이 일정 이상이면 끊어지는 관절" 같은 것을 만들기 쉽다.
그 뒤 Macklin 외의 Small Steps in Physics Simulation(SCA 2019)은 큰 걸음 하나에 반복 n번을 쓰는 것보다 걸음을 n개로 쪼개 각각 반복 1번을 쓰는 편이 오차와 감쇠가 훨씬 작다는 것을 보였다. 지금의 XPBD 구현은 대개 이 "작은 걸음(substep)" 방식으로 돈다.
천과 머리카락: 충돌, 바람, 긴 거리 제약
PBD 천은 정점을 입자로, 구조·전단 스프링을 거리 제약으로, 굽힘을 이웃 삼각형 사이 각도 제약(또는 한 칸 건너 거리 제약)으로 바꾼 것이다. 실제 천은 거의 늘어나지 않지만 쉽게 구부러지므로, 늘어남 제약은 단단하게(α ≈ 0), 굽힘은 부드럽게 준다.
충돌과 자기 충돌
몸과의 충돌은 보통 캡슐과 구 몇 개로 단순화한 충돌체에 대해 "표면 밖에 있어라"는 부등식 제약으로 처리한다. 어려운 것은 자기 충돌이다. 천이 접히면 천끼리 부딪치는데, 모든 정점과 삼각형 쌍을 검사할 수 없으니 공간 해시로 가까운 쌍만 찾고, 천에 얇은 두께를 줘 입자끼리 그 거리 안으로 들어오지 못하게 한다. 한 걸음에 두께보다 멀리 움직이면 서로 뚫고 지나가 엉킨 상태가 되므로, 걸음을 잘게 쪼개거나 속도를 제한한다. 넓은 판정과 좁은 판정의 일반론은 게임 개발 › 물리에 있다.
바람
바람은 공기를 풀지 않고 삼각형마다 힘을 준다. 삼각형의 법선 n, 넓이 A, 바람과 천의 상대 속도 vrel로 F ∝ A·(vrel·n)·n 정도를 주면, 바람을 정면으로 받는 면만 밀리고 바람과 나란한 면은 그대로라 깃발이 펄럭이는 모양이 저절로 나온다. 여기에 시간에 따라 흔들리는 노이즈를 곱해 돌풍을 만든다.
머리카락, 로프, 긴 거리 제약
머리카락과 로프는 마디를 거리 제약으로 이은 사슬이다. 문제는 사슬이 길면 고정점에서 끝까지 제약을 한 바퀴 도는 동안 수정이 한 마디씩만 전해져, 반복이 적으면 줄 전체가 고무줄처럼 늘어난다는 것이다. Kim, Chentanez, Müller-Fischer의 Long Range Attachments(SCA 2012)는 게임 캐릭터의 옷이 대개 어깨나 허리 같은 애니메이션된 부위에 붙어 있다는 점을 이용한다. 각 입자가 붙은 점에서 "쉬는 상태의 거리보다 멀어지지 않는다"는 한쪽 방향 제약을 하나씩 더하면, 반복 몇 번만으로도 전체가 늘어나지 않는다. 머리카락에는 Müller, Kim, Chentanez의 Fast Simulation of Inextensible Hair and Fur(VRIPHYS 2012)처럼 뿌리에서 끝으로 가며 각 마디를 앞 마디 쪽으로 당겨 한 바퀴 만에 길이를 맞추는 follow-the-leader 방식도 쓰인다.
연체, 파괴, 소성
젤리, 근육, 고무공처럼 부피를 가진 변형체는 천보다 제약이 하나 더 필요하다. 표면만 스프링으로 이으면 풍선처럼 쭈그러들기 때문이다. PBD 계열에서는 사면체 메시를 만들고 각 사면체의 부피 제약을 더하거나, 닫힌 표면 전체의 부피를 하나의 제약으로 둔다.
형상 일치(shape matching)
Müller 외의 Meshless Deformations Based on Shape Matching(SIGGRAPH 2005)는 연결 정보 없이 점 구름만으로 연체를 만든다. 매 걸음 쉬는 모양을 회전과 이동만으로 지금 점들에 가장 잘 겹친 위치(목표)를 구하고, 각 점을 목표 쪽으로 강성만큼 끌어당긴다. 가장 잘 맞는 회전은 점들의 상관 행렬을 극분해해 얻는다(2차원에서는 각도 하나의 닫힌 꼴). 목표가 언제나 쉬는 모양과 합동이므로 어떤 상황에서도 터지지 않는다는 것이 장점이고, 물리 재료 상수와 바로 이어지지 않는 것이 단점이다.
유한 요소법(FEM) 개요
재료의 실제 성질(영률, 푸아송 비)로 행동해야 할 때는 유한 요소법을 쓴다. 물체를 사면체로 나누고, 사면체가 쉬는 모양에서 얼마나 늘고 비틀렸는지(변형 기울기)를 재서 탄성 에너지를 구하고, 그 에너지의 기울기가 각 정점에 걸리는 힘이 된다. 같은 재료면 메시를 바꿔도 같은 행동을 한다는 것이 질량-스프링과의 결정적 차이다. 회전이 크면 단순한 선형 모델이 부풀어 오르는 문제가 있어 회전을 빼고 계산하는 공회전(corotational) 방식이나 비선형 재료 모델을 쓴다. 유한 요소법의 수학은 계산 과학 노트에 있고, XPBD도 사면체 FEM 에너지를 제약으로 바꿔 풀 수 있다.
소성과 파괴
소성은 탄성 한계(항복점)를 넘은 만큼 "쉬는 모양 자체"를 옮겨 적는 것이다. 철판이 찌그러진 채로 남는 이유다. 시뮬레이션에서는 요소의 변형이 항복값을 넘으면 그 초과분만큼 쉬는 길이나 쉬는 모양을 갱신한다. 파괴는 변형이나 제약 힘(XPBD의 λ)이 한계를 넘을 때 제약을 지우거나 메시를 쪼개는 것이다. 재료가 왜 그렇게 행동하는지는 재료과학 노트에, 게임에서 미리 잘라 둔 보로노이 조각으로 파괴를 연출하는 방법은 게임 개발 › 물리에 있다.
격자 유체: Stable Fluids
Jos Stam의 Stable Fluids(SIGGRAPH 1999)는 그때까지 불안정해 실시간에 쓰기 어렵던 유체 풀이를 "어떤 시간 간격에서도 터지지 않게" 만들었다. 방정식을 항별로 쪼개 한 걸음에 차례로 적용한다. 힘 더하기 → 이류 → 확산 → 압력 투영이다. 게임 개발자용으로 짧은 코드와 함께 다시 쓴 글이 Real-Time Fluid Dynamics for Games(GDC 2003)다.
확산: 암시적으로 푼다
확산은 각 칸이 이웃과 값을 나누는 과정이다. 명시적으로 풀면 한 걸음에 이웃으로 넘기는 비율 a = ν·dt/dx²가 1/2을 넘는 순간 값이 칸마다 부호를 바꾸며 불어난다. Stam은 이를 "걸음이 끝난 뒤의 값으로 이웃과 나눈다"는 암시적 식으로 바꿔 풀었다(논문 코드에서는 가우스-자이델 반복, 아래 그림은 삼중 대각 행렬을 바로 푼 결과). 그러면 a가 아무리 커도 값이 음수가 되거나 불어나지 않는다.
이류: 거슬러 올라가 읽는다
이류는 값을 흐름에 실어 옮기는 단계다. 칸의 값을 앞으로 밀어 보내는 대신, Stam은 준라그랑주(semi-Lagrangian) 방식으로 거꾸로 묻는다. "이 칸에 지금 도착한 물질은 dt 전에 어디 있었나?" 칸 중심에서 속도를 거슬러 따라가 그 자리의 옛 값을 이웃 칸에서 보간해 읽는다. 보간한 값은 이웃 값들 사이에 있으므로 새 최댓값이 옛 최댓값을 넘을 수 없고, 그래서 시간 간격이 커서 한 걸음에 여러 칸을 건너도 터지지 않는다. 대가는 보간할 때마다 조금씩 값이 뭉개지는 수치 확산이다. 연기가 금세 흐릿해지는 이유이고, 이를 줄이려고 고차 보간이나 MacCormack 같은 보정법, 뒤에 나오는 FLIP을 쓴다.
압력 투영: 발산을 빼낸다
힘과 이류를 거친 속도장은 비압축 조건을 어긴다. 어떤 칸에는 들어오는 것보다 나가는 것이 많다. 투영은 각 칸의 발산을 재고, 이웃 칸과의 압력 차가 그 발산을 정확히 지우도록 하는 압력을 푸아송 방정식으로 구한 뒤, 압력 기울기를 속도에서 뺀다. 수학적으로는 어떤 속도장이든 "발산 없는 부분"과 "어떤 함수의 기울기"의 합으로 유일하게 쪼갤 수 있다는 헬름홀츠-호지 분해이고, 투영은 뒤의 것을 버리는 일이다. 압력은 보통 가우스-자이델이나 야코비 반복, 큰 격자에서는 전처리 켤레 기울기법이나 다중 격자법으로 푼다. 아래 그림은 Bridson의 강의 노트가 권하는 엇갈린(MAC) 격자로 계산했다. 속도를 칸 면에, 압력을 칸 중심에 두면 칸을 드나드는 양을 바로 잴 수 있다.
SPH: 입자로 푸는 유체
SPH(smoothed particle hydrodynamics)는 유체를 입자 구름으로 보고, 어떤 점의 값을 근처 입자 값의 가중 평균으로 정한다. 가중치를 주는 함수가 커널 W(r, h)로, 거리 r이 반경 h를 넘으면 0이 되고 3차원 공간에서 적분하면 1이다. 입자 i의 밀도는 ρi = Σ mj·W(|xi − xj|, h), 압력은 상태 방정식 p = k(ρ − ρ0)로 밀도가 쉬는 밀도 ρ0보다 높으면 밀어 내는 값이 된다. 간격 1인 고른 격자에 질량 1인 입자를 놓고 h = 2인 poly6 커널로 재면 밀도가 1.010로, 정답 1에 가깝게 나온다.
Müller, Charypar, Gross의 Particle-Based Fluid Simulation for Interactive Applications(SCA 2003)는 용도마다 커널을 달리 쓰는 실시간 SPH를 제시했다. 밀도에는 거리 제곱만으로 계산되는 poly6, 압력에는 spiky, 점성에는 라플라시안이 늘 양수인 별도 커널이다. 이유는 아래 그림의 오른쪽에 있다. poly6의 기울기는 가운데에서 0이라, 입자가 겹칠수록 오히려 밀어 내는 힘이 사라져 입자가 뭉친다. spiky는 가까울수록 더 세게 민다.
SPH는 튀는 물, 물보라처럼 표면이 쪼개지는 장면에 강하고 경계 처리가 자연스럽다. 약점은 비압축이 근사라는 점이다. 상태 방정식의 k를 키우면 덜 눌리지만 강성 문제가 다시 생겨 dt가 작아진다. 그래서 반복으로 밀도를 맞추는 PCISPH, IISPH, DFSPH 같은 변형과, 밀도 조건을 PBD 제약으로 바꾼 위치 기반 유체가 나왔다. 이웃 찾기는 셀 크기 h인 공간 해시 격자로 한다. Macklin 외의 Unified Particle Physics(2014)는 천, 강체, 유체, 로프를 모두 같은 입자와 PBD 제약으로 풀어 서로 섞이게 했다.
FLIP/PIC와 MPM: 입자와 격자를 섞는다
격자는 압력 풀이에 좋고, 입자는 이류에 좋다. PIC(particle-in-cell)는 둘을 합친다. 입자가 속도를 들고 다니다가, 매 걸음 근처 격자로 속도를 옮기고(가중 평균), 격자에서 힘과 압력을 풀고, 다시 입자로 속도를 가져온다. 문제는 옮길 때마다 평균을 내니 작은 소용돌이가 사라진다는 것이다. FLIP(fluid-implicit-particle)은 격자의 새 속도를 그대로 가져오지 않고, 격자에서 "바뀐 만큼"만 입자 속도에 더한다. Zhu와 Bridson의 Animating Sand as a Fluid(SIGGRAPH 2005)가 이를 그래픽스의 비압축 유체에 가져왔고, 지금 영화의 물 시뮬레이션 상당수가 이 계열이다.
이 실험에서 PIC는 한 번 옮긴 것만으로 운동 에너지의 13%만 남는다. 실제 장면에서는 격자 해상도에 비해 입자가 많고 속도장이 매끄러워 이렇게 극적이지 않지만, 방향은 같다. 그래서 FLIP 95% + PIC 5%처럼 섞어 잡음과 감쇠 사이에서 균형을 잡고, 각운동량을 보존하도록 고친 APIC 같은 변형도 쓴다.
MPM(material point method)은 같은 입자-격자 구조에 연속체 역학을 얹는다. 입자가 속도뿐 아니라 변형 기울기(얼마나 늘고 비틀렸는지)를 들고 다니고, 격자에서 응력을 계산한다. 탄성, 소성, 파괴를 한 틀에서 다룰 수 있어 눈, 모래, 진흙, 반죽처럼 고체와 액체 사이의 재료에 강하다. Stomakhin 외의 A Material Point Method for Snow Simulation(SIGGRAPH 2013)이 그래픽스에서 MPM을 널리 알린 논문이다. 격자가 자기 충돌과 쪼개짐을 자동으로 처리해 주는 대신 계산이 무거워 아직은 주로 오프라인 VFX에서 쓴다.
물 표면, 연기, 불
얕은 물과 높이장 파도
호수나 웅덩이처럼 수면만 보이면 3차원 유체를 풀 필요가 없다. 수면을 2차원 격자의 높이장으로 두고, 각 칸의 높이가 이웃 평균으로 끌려가는 파동 방정식을 풀면 물결이 퍼지고 벽에서 되돌아온다. 칸마다 높이와 수직 속도만 들고 있어 GPU에서 수십만 칸을 매 프레임 돌릴 수 있다. 쿠랑 수 c·dt/dx가 1을 넘으면 터진다는 조건만 지키면 된다. 높이 대신 칸 사이의 물 흐름까지 다루는 얕은 물 방정식은 물이 흘러 넘치는 장면에 쓴다. 게임에서 이런 물결을 렌더링하는 연출은 게임 개발 › 이펙트의 수면 물결 절에 있다.
FFT 바다(Tessendorf)
넓은 바다는 시뮬레이션하지 않고 통계로 합성한다. Jerry Tessendorf의 강의 노트 Simulating Ocean Water는 바다 표면을 서로 다른 파장과 방향의 사인파 수만 개의 합으로 보고, 파장별 크기는 해양학의 관측 스펙트럼(필립스 스펙트럼 등)에서, 시간에 따른 움직임은 깊은 물의 분산 관계 ω = √(g·k)에서 가져온다. 긴 파도일수록 빠르다. 파장 10m 파도는 주기 2.53초, 속도 4.0m/s이고, 100m 파도는 12.5m/s로 달린다. 이 합을 FFT 한 번으로 계산하므로 수십만 개 성분도 프레임마다 다시 더할 수 있고, 결과는 이음매 없이 바둑판처럼 이어 붙일 수 있다. 노트 서문은 Waterworld와 Titanic의 바다를 이 계열 작업의 선구로 든다.
위 그림의 곡선은 방향 성분을 뺀 크기다. 실제로는 바람 방향과 나란한 파도만 살리는 방향 항을 곱하고, 수평으로 출렁이는 성분(뾰족한 물마루)과 파도 꼭대기의 거품을 더한다. 게르스트너 파도와 바다 렌더링 연출은 게임 개발 › 이펙트에 있다.
연기와 불
연기와 불은 Stable Fluids 격자 위에 스칼라장 몇 개를 더 실어 나른 것이다. 밀도(연기의 짙기), 온도, 연료를 같은 속도장으로 이류하고, 온도가 주변보다 높은 곳에 위로 향하는 부력을 준다. 수치 확산 때문에 사라지는 작은 소용돌이는 와도 가둠(vorticity confinement)으로 되살린다. 소용돌이의 중심을 찾아 그 둘레의 회전을 북돋는 가짜 힘이다. 불은 연료가 타며 열과 연기를 만들고 온도가 서서히 식는 규칙을 더하고, 렌더링 때 온도를 흑체 색으로 바꾼다.
GPU 병렬화
격자 유체는 GPU와 궁합이 좋다. 칸마다 같은 계산을 하므로 칸 하나를 스레드 하나에 맡기면 된다. 이류는 칸마다 독립이고, 압력 풀이는 순서에 묶인 가우스-자이델 대신 이전 값만 읽는 야코비 반복을 쓴다. 수렴은 느리지만 수천 칸을 동시에 고칠 수 있어 결과적으로 빠르다. Mark Harris의 GPU Gems 38장은 압력에 야코비 반복을 수십 번 쓰도록 권한다.
PBD는 까다롭다. 두 제약이 같은 입자를 동시에 고치면 서로의 결과를 덮어쓴다. 해결책은 둘이다. 하나는 그래프 색칠로, 같은 입자를 공유하지 않는 제약끼리 묶어 한 묶음을 병렬로 풀고 묶음 사이에서만 순서를 지킨다. 다른 하나는 야코비식으로 각 제약의 수정량을 입자별로 더해 두었다가 개수로 나눠 한꺼번에 적용하는 것이다. 수렴은 느리지만 색칠이 필요 없다. 병렬 프로그래밍의 일반론은 병렬 프로그래밍과 HPC 노트, GPU 구조는 GPU 노트에 있다.
SPH와 FLIP은 이웃 찾기가 병목이다. 입자를 공간 해시의 셀 번호로 정렬해 같은 셀 입자가 메모리에 붙어 있게 하면 캐시와 메모리 대역폭을 덜 쓴다. 격자로 입자 값을 옮기는 단계는 여러 입자가 같은 칸에 쓰므로 원자적 덧셈을 쓰거나, 칸 입장에서 주변 입자를 모아 읽는 방식으로 바꾼다.
게임의 속임수
게임에서 화면의 천과 물 대부분은 시뮬레이션이 아니다. 프레임 예산 16.7ms(60fps) 안에 렌더링, AI, 게임 물리까지 들어가야 하므로 "보는 사람이 차이를 모르는 가장 싼 방법"을 고른다. 시뮬레이션은 그 가운데 하나의 선택지다.
| 보이는 것 | 흔한 속임수 | 실제 시뮬레이션은 언제 |
|---|---|---|
| 망토, 치마, 깃발 | 뼈대(본)를 몇 개 심어 애니메이션하거나, 뼈대마다 스프링을 단 "흔들림 본"으로 출렁임만 흉내 낸다 | 주인공 옷처럼 화면을 오래 차지하고 몸과 닿는 경우. 그래도 몸에 붙은 부분은 애니메이션이 정한다 |
| 머리카락 | 머리카락 다발 메시에 뼈대 사슬 몇 줄. 시뮬레이션은 뼈대 수십 개만 | 낱가닥 렌더링을 하는 고사양 캐릭터. 가닥 일부만 풀고 나머지는 보간한다 |
| 폭발, 연기, 불 | 미리 계산한 시뮬레이션을 텍스처 여러 장으로 구운 플립북을 파티클에 붙인다 | 캐릭터가 지나가면 연기가 갈라지는 등 상호작용이 보여야 할 때. 낮은 해상도 3D 격자를 쓴다 |
| 바다, 호수 | 정점 셰이더에서 사인파나 게르스트너 파도 몇 개를 더하거나, FFT 높이장 텍스처를 타일로 반복한다 | 배가 만드는 물결, 물이 넘쳐 흐르는 장면. 근처만 높이장이나 얕은 물로 푼다 |
| 물 튀김, 피 | 파티클과 데칼 | 컷신이나 VFX 영상. 오프라인 FLIP이나 SPH를 돌려 메시나 캐시로 굽는다 |
이 표의 오른쪽 열에서도 "굽기(baking)"가 자주 나온다. VFX와 시네마틱에서는 몇 시간짜리 오프라인 시뮬레이션을 돌려 정점 애니메이션이나 볼륨 캐시로 저장하고, 게임 안에서는 그것을 재생만 한다. 실시간이 필요한 것은 플레이어의 입력에 반응해야 하는 부분뿐이다. 반응의 느낌(타격감, 흔들림)을 조절하는 이야기는 게임 개발 › 조작감에 있다.
흔한 오해
- "시간 간격을 줄이면 무조건 정확해진다." 명시적 오일러는 dt를 줄여도 감쇠 없는 진동에서 에너지가 계속 는다. 늘어나는 속도가 느려질 뿐이다. 안정성은 dt만이 아니라 적분 방식과 강성의 조합으로 정해진다.
- "암시적 적분은 정확하다." 암시적 오일러는 안정할 뿐 정확하지 않다. 큰 걸음에서는 에너지가 빠져 모든 것이 둔해지고, 그 감쇠를 재질의 성질로 착각하기 쉽다.
- "PBD의 강성 값은 재료의 단단함이다." 원래 PBD의 강성은 반복 횟수와 시간 간격에 따라 효과가 달라진다. 반복 횟수를 성능 옵션으로 바꾸면 천의 재질이 바뀐다. 물리적 의미가 필요하면 XPBD의 컴플라이언스를 쓴다.
- "유체 시뮬레이션은 나비에-스토크스를 정확히 푼다." 그래픽스의 유체는 수치 확산, 근사 압력, 낮은 해상도로 물리적으로 꽤 틀린 답을 낸다. 목표는 그럴듯한 움직임이고, 그래서 와도 가둠 같은 가짜 힘을 일부러 더한다. 공학용 전산 유체 역학(CFD)과는 목적과 검증 방식이 다르다.
- "SPH 입자 하나가 물 분자 하나다." 입자는 물의 작은 덩어리를 대표하는 표본이다. 입자 수를 늘리면 해상도가 오를 뿐 분자 수준에 가까워지는 것이 아니다.
- "게임의 물과 천은 다 시뮬레이션이다." 대부분은 뼈대 애니메이션, 플립북, 정점 셰이더 파도, 구운 캐시다. 실시간 시뮬레이션은 상호작용이 보여야 하는 곳에만 아껴 쓴다.
- "반복을 더 돌리면 늘어남이 사라진다." 긴 사슬에서는 수정이 반복 한 번에 한 마디씩만 전해져 반복 비용 대비 효과가 낮다. 긴 거리 제약, 작은 걸음 쪼개기, 다중 격자처럼 구조를 바꾸는 편이 훨씬 싸다.
핵심 자료
강체와 충돌 응답은 게임 물리학 노트, 수치 적분과 유한 요소법은 계산 과학 노트, 벡터와 행렬은 게임 개발 수학 노트에 있다. 처음 직접 만들어 보려면 Ten Minute Physics의 천 예제와 Stam의 GDC 2003 글부터 따라 하는 것을 권한다.
| 자료 | 종류 | 요지 | 링크 |
|---|---|---|---|
| Ten Minute Physics | 강의 영상·예제 | PBD를 만든 Matthias Müller의 10분짜리 강의 모음. 천, 자기 충돌, 연체, 오일러 유체, FLIP 물, 높이장 물, 불까지 브라우저에서 돌아가는 짧은 JavaScript 예제와 함께 보여 준다. | Matthias Müller |
| Fluid Simulation (SIGGRAPH 2007 Course Notes) | 무료 강의 노트 | Bridson과 Müller-Fischer의 강의 노트. MAC 격자, 이류, 압력 투영, 표면 추적, 높이장 근사까지 그래픽스 유체의 표준 입문서다. | UBC (PDF) |
| Stable Fluids | 논문(1999) | Jos Stam. 준라그랑주 이류와 압력 투영으로 시간 간격과 상관없이 터지지 않는 유체 풀이를 처음 제안했다. | University of Toronto (PDF) |
| Real-Time Fluid Dynamics for Games | 발표 논문(GDC 2003) | Stable Fluids를 게임 개발자용으로 줄인 글. 2차원 밀도·속도 풀이를 짧은 C 코드로 처음부터 끝까지 보여 준다. | University of Toronto (PDF) |
| Position Based Dynamics | 논문(2006) | Müller 외. 힘 대신 위치를 직접 제약에 맞춰 고치는 방법. 예측, 제약 투영, 속도 갱신의 틀과 반복 횟수 보정이 여기서 나왔다. | Matthias Müller (PDF) |
| XPBD: Position-Based Simulation of Compliant Constrained Dynamics | 논문(2016) | Macklin 외. 제약마다 라그랑주 승수와 컴플라이언스를 두어 강성이 반복 횟수와 시간 간격에 끌려가지 않게 했다. | Matthias Müller (PDF) |
| Simulating Ocean Water | 강의 노트 | Jerry Tessendorf. 게르스트너 파도, 분산 관계, 필립스 스펙트럼과 FFT로 바다 높이장을 만드는 방법. 영화와 게임 바다의 출발점이다. | Clemson University (PDF) |
| Fast Fluid Dynamics Simulation on the GPU | 책 한 장(GPU Gems) | Mark Harris. Stable Fluids를 프래그먼트 셰이더로 옮기고 압력을 야코비 반복으로 푸는 법. GPU 유체의 고전이다. | NVIDIA Developer |
| University Physics Volume 1, 14장 유체 역학 | 무료 교과서 | 밀도와 압력, 부력, 연속 방정식, 베르누이 방정식, 점성과 난류를 대학 교양 수준으로 다룬다. 이 노트의 물리 바탕이다. | OpenStax |
- Ten Minute Physics — Matthias Müller
- Fluid Simulation (SIGGRAPH 2007 Course Notes) — UBC (PDF)
- Stable Fluids — University of Toronto (PDF)
- Real-Time Fluid Dynamics for Games — University of Toronto (PDF)
- Position Based Dynamics — Matthias Müller (PDF)
- XPBD: Position-Based Simulation of Compliant Constrained Dynamics — Matthias Müller (PDF)
- Simulating Ocean Water — Clemson University (PDF)
- Fast Fluid Dynamics Simulation on the GPU — NVIDIA Developer
- University Physics Volume 1, 14장 유체 역학 — OpenStax
- Large Steps in Cloth Simulation (Baraff, Witkin 1998) — CMU (PDF)
- Advanced Character Physics (Jakobsen) — CMU 강의 자료 (PDF)
- Small Steps in Physics Simulation (Macklin 외 2019) — PDF
- Long Range Attachments (Kim, Chentanez, Müller-Fischer 2012) — PDF
- Fast Simulation of Inextensible Hair and Fur (Müller, Kim, Chentanez 2012) — PDF
- Meshless Deformations Based on Shape Matching (Müller 외 2005) — PDF
- Particle-Based Fluid Simulation for Interactive Applications (Müller 외 2003) — PDF
- Animating Sand as a Fluid (Zhu, Bridson 2005) — UBC (PDF)
- A Material Point Method for Snow Simulation (Stomakhin 외 2013) — Disney Animation
- Unified Particle Physics for Real-Time Applications (Macklin 외 2014) — PDF