
개요
잉크 이펙트 제작법을 알아본다.
실오라기 같은 이펙트 리소스가 필요할 때 굉장히 유용하다.
Pop Advect..가 가장 많이 쓰는 방법이지만, 최적화된 워크플로우를 알려주는 좋은 글이라 소개한다.
내용
https://pepefx.blogspot.com/2014/07/ink-in-water.html
Ink in Water
A blog about FX techniques, ideas and algorithms developed using Houdini.
pepefx.blogspot.com
1. 튜토리얼 개요 및 핵심 아이디어
이 튜토리얼은 물속에 잉크가 퍼져나가는 유기적이고 복잡한 형태의 비주얼 이펙트(VFX)를 제작하는 과정을 다룹니다.
핵심 아이디어는 두 단계를 분리하는 것입니다.
- 유체 시뮬레이션: 먼저 연기(Smoke) 시뮬레이션을 통해 복잡한 움직임을 가진 속도장(Velocity Field) 데이터만 생성합니다.
- 파티클 렌더링: 이 속도장을 이용해 수백만 개의 파티클을 움직여(Advect) 최종적인 잉크의 형태를 만듭니다.
저자는 유체 시뮬레이션 결과물 자체를 렌더링하지 않고, 그 '움직임 데이터'만을 활용하는 방식을 택했습니다.
이는 파티클을 사용해야 훨씬 더 세밀하고 풍부한 디테일을 표현할 수 있기 때문입니다.
만약 동일한 디테일을 유체 시뮬레이션(가스 그리드)만으로 구현하려면 엄청난 해상도가 필요해 비현실적이라고 판단한 것입니다.
이는 성능과 비주얼 퀄리티 사이의 균형을 고려한 매우 실용적인 워크플로 설계입니다.
2. 기술적 워크플로 상세 분석
1단계: 속도장(Velocity Field) 생성
- 툴: Houdini 13의 Smoke Solver를 사용했습니다. 더 복잡한 Pyro Solver 대신 가벼운 Smoke Solver를 선택한 것은, 필요한 것이 '속도' 데이터뿐이므로 굳이 무거운 툴을 쓸 필요가 없다는 효율성 중심의 판단입니다.
- 다양성 확보 (Wedge): 한 가지 시뮬레이션만 만들지 않고, Wedge 기능을 활용했습니다. 난기류(Turbulence)의 강도, 소용돌이 반경(Twirl Radius) 같은 파라미터를 조금씩 바꿔가며 10가지 버전의 시뮬레이션을 생성하고 디스크에 캐시(Cache)했습니다.
- 시사점: 이 방식은 최종 결과물에 풍부한 변화와 예측 불가능성을 더해줍니다. 여러 개의 속도장 데이터를 확보해두면, 하나의 소스로 다양한 형태의 이펙트를 만들거나 여러 이펙트를 합성(Compositing)할 때 유용하게 사용할 수 있습니다.
2단계: 파티클 애드벡션(Particle Advection)
생성된 속도장을 이용해 파티클을 움직이는 단계에서, 저자는 Houdini의 두 가지 방법을 비교하고 최적의 선택을 합니다.
| 방법 | 장점 | 단점 |
| POP 시스템 (POP Advect by Volumes 노드) | 파티클의 움직임을 제어하는 다양한 노드(예: POP Drag, POP Wind)를 쉽게 추가할 수 있어 제어와 확장이 용이합니다. | 속도가 매우 느립니다. |
| VDB + SOP Solver (VDB Advect Points 노드) | VDB(Volume DataBase) 포맷을 활용하여 압도적으로 빠릅니다. 초당 수백만 개의 파티클 처리가 가능합니다. | 모든 설정을 직접 구성해야 하는 번거로움이 있습니다. |
저자는 VDB 방식을 채택했습니다. 그 이유는 압도적인 속도 덕분에 훨씬 더 많은 파티클을 사용하여 시뮬레이션 단계에서부터 최종 렌더링에 가까운 밀도와 디테일을 확보할 수 있기 때문입니다. 이는 "파티클 느낌(Particulate look)"을 줄이기 위해 후반 작업에서 여러 결과물을 합성하는 과정을 최소화하려는 전략적 선택입니다.
3단계: 디테일 추가 (Filling Gaps)
파티클 시뮬레이션을 하다 보면 움직임 때문에 파티클이 드문드문해지는 영역이 생길 수 있습니다. 이를 보완하기 위해 **Attribute Wrangle 노드(VEX 코드)**를 사용해 파티클 사이의 빈 공간을 채워 넣습니다.
- 작동 원리: 특정 반경 내에서 다른 파티클과 너무 멀리 떨어진 파티클을 찾아, 그 사이에 새로운 파티클을 생성합니다.
- 기술적 포인트: 이 알고리즘이 완벽하지는 않지만, 애니메이션 내내 일관성 있게 작동하여 렌더링 시 파티클이 갑자기 나타나거나 사라지는 아티팩트(Artifacts)가 발생하지 않는다는 점이 중요합니다.
3. 렌더링 및 최종 합성
- 렌더링: Houdini의 기본 렌더러인 Mantra를 사용하여 10가지 버전의 파티클 애니메이션을 각각 EXR 이미지 시퀀스로 렌더링합니다.
- 합성(Compositing): Nuke와 같은 툴에서 이 이미지 시퀀스들을 가져와 스프라이트(Sprite)처럼 활용합니다.
- 최종 터치: 큰 평면에 흩뿌리듯 배치하고, 피사계 심도(Depth of Field) 효과를 적용하여 공간감과 사실감을 더하며 마무리합니다.
요약
최적화 핵심은 이 부분이다.
convert the velocity to VDB, merge the fields into one single VDB vector field (with VDB Vector Merge - don't worry if Houdini complains cause the grid components are different), then use VDB Advect Points in a SOP Solver to advect your points.
속도를 VDB로 변환한 후, 필드를 단일 VDB 벡터 필드로 병합합니다(VDB Vector Merge를 사용하세요. Houdini가 그리드 구성 요소가 다르다고 경고하더라도 걱정하지 마세요). 그런 다음 SOP Solver에서 VDB Advect Points를 사용하여 점을 이동시킵니다.
그리고 비어있는 파티클을 채우는 부분이다.
In order to add extra points in the areas where the particles were more sparse, I added an Attribute Wrangle node in the end of the chain and I called it Fill Gaps. Since Attribute Wrangle works in the CVEX context, I am given the opportunity to add (or destroy) geometry.
The purpose of the script is basically adding points where there aren't.
This is the content of the script (make sure to create the proper UI parameters before sourcing the script) and feed the same point geometry both in input 1 and 2 of the Attrib Wrangle node.
입자 밀도가 낮은 영역에 추가 점을 추가하기 위해 체인의 끝에 Attribute Wrangle 노드를 추가하고 이를 'Fill Gaps'라고 명명했습니다. Attribute Wrangle은 CVEX 컨텍스트에서 작동하기 때문에 기하학을 추가하거나 제거할 수 있는 기회를 제공합니다.
이 스크립트의 목적은 기본적으로 점이 없는 곳에 점을 추가하는 것입니다.
이 스크립트의 내용입니다(스크립트를 실행하기 전에 적절한 UI 매개변수를 생성해야 합니다). Attrib Wrangle 노드의 입력 1과 2에 동일한 점 지오메트리를 입력으로 전달합니다.
float searchrad=ch("searchrad");
float mindist=ch("mindist");
int maxpoints=ch("maxpoints");
int fillpoints=ch("fillpts");
vector clpos;
int handle=pcopen(@OpInput2,"P",@P,searchrad,maxpoints+1);
int i=0;
while(pciterate(handle))
{
if (i==0) // the first point found should be the closest, in this case, itself. We want to skip it.
{
i++;
continue;
}
pcimport(handle,"P",clpos);
if (length(@P-clpos)>mindist)
{
vector pointstep=(clpos-@P)/(fillpoints*2+1); // this ensures there are no duplicate point
// at the cost of doubling the fill points number
for (int t=0;t<fillpoints;t++)
addpoint(geoself(),@P+(pointstep*float(t+1)));
}
}
비고
아쉽게도 해당 글은 hip 파일 다운 권한이 막혀있다.
그런데 vdb를 사용하는 방식은 이전 게시글인 담배 연기 제작법에 있으므로, 해당 부분을 참고하면 되겠다.
그리고 VEX 코드만 적절히 집어넣으면 될 것이다.
https://monggus.tistory.com/859
[Houdini] 담배 연기 만드는 법 소개 (Cigarette Smoke)
개요후디니에서 샤프한 연기를 만드는 노하우를 소개하는 아티클이다. 내용파트 1: Cigarette Smoke (2016년 4월)이 글은 Houdini를 사용하여 사실적인 담배 연기를 만드는 방법에 대한 초기 튜토리얼입
monggus.tistory.com
'이펙트 (FX) > 이펙트 팁 : Houdini' 카테고리의 다른 글
| [Houdini] RBD Cluster 올바른 사용법 (0) | 2025.08.26 |
|---|---|
| [Houdini] 뷰포트 색공간을 ACES로 설정하기 (Color Space, ACES의 중요성) (1) | 2025.08.24 |
| [Houdini] 담배 연기 만드는 법 소개 (Cigarette Smoke) (0) | 2025.08.19 |
| [Houdini] 뷰포트 Secure Selection 기능 장단점 (연속 선택, 연속 편집시 필수) (0) | 2025.08.15 |
| [Houdini/RBD] Deforming 오브젝트의 Constraint 업데이트 오류 해결법 (Destruction) (0) | 2025.08.15 |
댓글