안녕하세요. 정글러입니다.
오늘은 Stable Fluids를 구현하는 알고리즘을 살펴보겠습니다.
stable fluids는 입자 애니메이션이 아닌, 격자 시뮬레이션입니다.
입자(particle)은 구조가 정해져있지 않고, 자기 자신이 움직이기 때문에 매번 이웃을 찾아야 하는 어려움이 있습니다.
반면, 격자(Grid)는 이웃들이 고정되어 있어 미분 구하기가 편하지만 움직임 표현이 어렵습니다.
Navier-Stoke equation은 격자 시뮬레이션 방법을 제시합니다.
Chorin's progection method를 참고해서 공부해보겠습니다.
"속도(u)가 시간에 대해서 어떻게 변하는지"가 궁극적인 목표입니다.
1. Advection
가로 방향으로 가는 속도장을 따라서 밀도가 흘러가는 것을 의미합니다.
density값들이 오른쪽으로 옮겨지는 것처럼 보이려면 Grid에서 업데이트하고 싶은 속도를 역추적해서 샘플링합니다.
HLSL | 언리얼 나이아가라 |
1. velocityTemp로부터 속도를 샘플링 | |
float2 vel = velocityTemp.SampleLevel(pointWrapSS, pos, 0).xy; | 속도값 샘플링 Sample Previous Grid Float |
2. 그 속도를 이용해서 역추적 위치 계산 | |
float2 posBack = pos - vel * dt; | 현재 셀의 위치 Execution Index to Unit (pos를 0~1로 정규화) dtID * DeltaTime |
3. 그 위치에서 샘플링 해오기 | |
velocity[dtID.xy] = velocityTemp.SampleLevel(linearWrapSS, posBack, 0); density[deID.xy] = densityTemp.sampleLevel(linearWrapSS, posBack, 0); |
2. Pressure Projection
* 속도장의 계산
Gradient / Divergence / Laplacian operator
Laplacian operator)
Gradient(속도장을 압력으로부터 보정하기 위해 사용)를 다시 미분한 것
가운데의 점은 이웃지점들을 더하고 이웃지점 개수만큼 곱해서 빼준다.
Divergence operator)
비압축성 조건을 표현 // 나가는 양(Ui+1+Vj+1) = 들어오는 양(Ui-1+Vj-1)
유체(연기, 물 등)의 경우엔 팽글 팽글 돌면서 움직입니다.
Grid에 압력을 가하면, 압력이 높은 곳에서 압력이 낮은 곳으로 이동합니다.
pressure가 구해지면 속도를 업데이트합니다.
이웃하는 픽셀들을 설정
uint2 left = uint(dtID.x - 1, dtID.y); | Make Vector 2d(-1,0) + Sample Previous Grid Float |
uint2 right = uint(dtID.x + 1, dtID.y); | Make Vector 2d(1,0) + Sample Previous Grid Float |
uint2 up = uint(dtID.x +, dtID.y + 1); | Make Vector 2d(0,1) + Sample Previous Grid Float |
uint2 up = uint(dtID.x +, dtID.y - 1); | Make Vector 2d(0,-1) + Sample Previous Grid Float |
Divergence
divergence[dtID.xy] = 0.5 * (velocity[right].x - velocity[left].x + velocity[up].y - velocity[down].y);
Jacobi interation (pressure 계산)
PressureOut[dtID.xy] = (-divergence[dtID.xy] + pressureTemp[left] + pressureTemp[right] + pressureTemp[down] + pressureTemp[up]) * 0.25;
ApplyPressure
float2 dp = float2(pressure[right] - pressure[left], pressure[up] - pressure[down]);
velocity[dtID.xy] -= dp * 0.5;
이렇게 계산한 식을 합치면!
녹화본이라 좀 깨져보이네요.
실제로는 부드럽게 잘 구현되었습니다!
감사합니다.
'XR > Graphics' 카테고리의 다른 글
[Graphics] RenderDoc 읽기 (0) | 2025.04.24 |
---|---|
[Graphics] Compute Shader 알아보기 (0) | 2025.04.03 |
[Graphics] Barycentric Coordinate System 알아보기 (0) | 2025.03.10 |
[Graphics] Rasterization과 Ray tracing의 차이 (0) | 2025.02.21 |
[Graphics] Phong Reflection Model(Ambient / Diffuse / Specular) 이해하기 (0) | 2025.02.04 |