TWA Houdini1/Volumes

TWA 후디니 1 Volume_06 : Solver와 함께 Volume 다루기

yiss09 2023. 2. 25. 05:01

 

https://www.twahoudini.com/course/volumes1

 

HOUDINI1_ VOLUMES

2️⃣ 볼륨의 기초이론과 응용 그리고 SIMULATION까지 경험해보세요.

www.twahoudini.com

 

Volume06에서는 Volume과 Solver를 동시에 활용하는 방법을 배우게 된다.

 

1. Volume에서의 Solver 활용

2. 다양한 형태의 Volume과 Solver

3. Gradient, Curvature와 Solver

4. 심화 예제


1. Volume에서의 Solver 활용

 

VDB Advect를 사용해 볼륨이 커지는 것처럼 묘사해보겠다.

Solver를 사용하기에 앞서 먼저 Geometry단계에서 한번의 사이클이 어떻게 작동되는지 구성해보겠다.

Sphere를 생성해준다. Frequency를 20까지 높여준다.

VDB Advect를 사용하기 위해 VDB from Polygons를 활용해 Polygons를 SDF VDB로 만든다.

VDB가 계속해서 커지게 만들기 위해선 Gradient의 정보가 필요할 것이다. VDB Analysis를 이용해 Gradient의 정보를 구해준다. 구해준 정보의 이름을 gradient로 변경해준다.

앞서 구한 VDB와 Gradient를 VDB Advect에 연결시켜준다.

VDB Advect로 결과를 확인해준다면, Gradient 정보에 따라 Timestep만큼 커진 Volume을 확인할 수 있다.

 

이제 Solver에서 해당 과정을 거쳐 지속적으로 커지는 Volume을 생성해보려한다.

 

앞으로 Volume에서 Solver를 활용할때의 기준이다.

1. 간단한 세팅일 때 시작과 끝의 정보(형태, 이름)가 같아야한다는 뉘앙스를 가지고 있어야한다. 그래야 앞으로 작업이 복잡해질 때 검토의 기준이 명확하게 생길 것이다.

2. 작업의 합리성과 효율성, VDB를 다루다보면 정보 손실이 많이 일어난다. 불필요한 계산이 늘어나는 것은 속도에 좋지 않은 영향을 준다. Volume을 다루면서 Solver를 쓸 때는 정말 필요한 정보만 넣어주는게 중요하다.

 

앞의 과정에서 Solver 안으로 들어갈 내용과 밖에 있을 내용을 구분지어준다.

Solver 내부에서의 시작과 끝의 정보가 같아야한다. 이를 기준으로 Solver 안으로 VDB Analysis와 VDB Advect를 넣어준다.

이때 VDB from Polygons를 같이 Solver 안으로 넣어도 작동은 된다. 하지만 그러지 않는 이유는 불필요한 계산을 줄여주기 위함이다.

 

Geometry 단계에서 Solver의 작동 방식을 묘사해보았다.

이전 Frame에서의 VDB Advect의 결과가 다음 Frame의 Null로 연결되어, 다시 Gradient가 분석되어 새로운 방향정보를 생성해내고 있다.

계속해서 커지고 있는 Volume을 볼 수 있다.

 

만약 Solver를 사용하지 않은 상태에서 VDB Advect에서의 Timestep 값만을 높여 크기를 맞춘다면, 그 값은 전혀 다른 값은 Solver에서와 전혀 다른 값이 된다는 것을 명심하자.

 

 


2. 다양한 형태의 Volume과 Solver

 

이번에는 닫혀있는 Polygons가 주어진다면, Solver에 의해 크기가 커지는 시스템을 Polygons, SDF Volume, Fog Volume의 결과로 만들보려한다.

만약 각각의 형태를 Solver로 이용하기 위해서는 어떠한 node가 Solver 안으로 들어가야 할지를 생각해보자.

 

먼저 이전의 예제에서 해보았던 SDF VDB를 Solver로 작동되게 만들어 보겠다.

SDF로 끝나는 부분과 시작하는 부분을 생각해, VDB Analysis와 VDB Advect를 Solver 내부로 이동시켰다.

Solver에 의해 Gradient를 계속하여 분석하며 커지는 SDF Volume을 만들었다.

 

Volume의 형태를 Polygons로 Solver에서 결과를 내고 싶다면, 시작부분의 형태도 Polygons여야 한다.

이때 나오게 되는 Polygons의 디테일이 부족하다고 느껴진다면, VDB from Polygons의 Voxel Size를 줄여주도록 하자.

 

Fog의 경우는 조금 특이하다. Solver를 활용해 계속해서 커지게 되는 Fog Volume을 만들게 된다면, 오히려 계속해서 축소하는 결과를 볼 수 있다.

 

Fog Isovalue : 0.5(좌측), 0.0001(우측)

그 이유는 바로 SDF Volume이 Fog Volume으로 전환되는 데에서 문제가 발생하게 된다. 더욱 커져야할 녀석이 부피가 상대적으로 부피가 작은 Fog Volume이로 전환되면서 이전 Frame에 비해 크기가 축소된 결과가 나오게 되는 것이다.

이러한 문제는 Convert VDB node의 Fog Isovalue 값을 0.5에서 매우 작은 값인 0.0001로 변경해준다면 다시 커지는 Fog Volume을 관찰할 수 있다.

이때 Fog Isovalue 값에 0.0001이 아닌 0을 넣게 된다면, Fog가 삭제되게 된다.

점점 커지는 Fog VDB를 만들었지만, 원했던 모양이 아닌 각진 모양이 나오게 되었다. 잘못된 방향으로 Solver를 설정한 것이 아닌지 Volume에서의 Solver 사용 기준을 중심으로 다시 고민해봐야할 필요가 있다.

 

 


3. Gradient, Curvature와 Solver

 

이번엔 Curvature와 Gradient를 활용해 튀어나온 부분은 더 튀어나오고 들어간 부분은 더 들어가게 만들어주려한다.

VDB Analysis로 Gradient 값과 Curvature 값을 구해준 뒤, Volume Vop에서 Gradient 값에 Curvature 값을 곱해준다.

그 다음 VDB Advect에 그 둘의 정보를 넣어줘 위의 사진과 같은 결과를 얻어냈다.

 

이제 값을 변경해 Volume이 Advect 되는 양상을 바꿔볼 것이다.

1. VDB Smooth로 모나있는 Curvature 값에 변화를 준다.

2. Advect되는 속도를 조절할 수 있게 만들어준다.

3. Vector Field 내에 다른 값들을 추가해준다. 위로 바람이 부는 것과 같이 묘사해주거나, Noise를 이용해 Curvature에 적용되는 부분이 달라질 수 있도록 꾸며줄수도 있을 것이다.

 

VDB Smooth를 활용해 쭈글쭈글한 느낌을 부드럽게 만들어주려한다.

Curvature의 정보가 들어간 VDB Analysis VDB Smooth를 연결해준다.

Filter Voxel Radius와 Iterations, 그리고 VDB Advect의 Timestep을 조절해 적당히 Smooth가 들어간 느낌으로 Teak해준다. 이때 TimeStep의 값이 작으면 작을수록 Detail한 결과를 얻을 수 있다.

Filter Voxel Radius는 기본적으로 한 칸의 voxel을 기준으로 Smooth를 발생시킨다. 이때 Use World Space Radius Units를 체크해주게 된다면 실제 거리값을 기준으로 Smooth를 발생시켜주게 된다.

 

이전의 사진을 보면 너무 움푹 패인 곳이 많아 Rubbertoy가 징그럽게 느껴진다.

안쪽으로 들어간 부분을 Clamp해주도록 하자. Curvature 아래 VDB Smooth 위에 Volume Vop을 생성한다.

Bind로 Curvature 값을 불러내어 Clamp해준다.

Curvature 값이 Float 값이기에 Clamp의 Signature를 Float으로 두었다.

최솟값은 -0.5로 두었다. -0.5 이하의 값들은 전부 -0.5로 고정되었다.

최댓값은 50으로 맞춰주었다.

움푹 패였던 부분들이 완화된 모습을 볼 수 있다.

 

이제 Volume에서의 voxel들이 Noise에 의해 각각 다르게 상승하는 듯한 효과를 가져보려한다.

상승하는 듯한 효과를 내기 위해 Constant에 vector.y 값을 높여준다. Curvature와 곱해진 Gradient 값에 Add 해준다.

그 다음 Anti-Aliased Flow Noise를 생성해 Constant 값과 곱해준다.

Add에 연결된 Constant 값을 해제해주고 Noise와 Multiply된 값을 다시 Add해준다.

Anti-Aliased Flow Noise와 Constant의 값을 원하는 느낌으로 Tweak 해준다.

 

뭔가 Noise를 먹으면서 상승하는 듯한 효과가 만들어졌다.

 

이제 Tweak을 하면서 앞서 배운것들을 체크해보자.

1. Solver Setting을 잘 잡을 수 있는가? 기준을 가지고 있는가?

2. 효과의 속도를 조절할 수 있는가? Timestep의 값을 이해했는가?

3. VectorField를 다룸에 있어 겁먹지 않고 정보들을 다룰 수 있는가?

 

방금 배운 것들을 잘 응용한다면, 어떠한 물체가 불에 타서 녹는 듯한 모습을 연출할 수 있을 것 같다.

 

 


4.  심화 예제

 

Copy to Points를 이용해 XZ Plane에서 원운동하는 Sphere(Polygons)를 생성해준다.

VDB from Polygons를 이용해 Fog VDB로 전환시켜준다.

 

이제 Solver를 활용해 움직임에 따라 잔상을 남기는 Volume을 만들어 볼 예정이다.

 

복잡한 작업에서는 먼저 Solver 밖에서 한 사이클이 어떻게 돌아갈지 계획을 잘 세워야 한다.

Volume 작업을 할 예정이기 때문에 Geometry와 같이 Attributes를 달고 다닌다는 느낌으로 접근하면 꼬일 수 있다. 명확하게 이름 구분을 잘 해 더할 것을 더해주고 버릴 것을 버려주도록 해야 한다.

 

사이클이 돌 것을 예상한다면, Prev_Frame이 논리적으로 알맞지 않은 느낌이다. Prev_Frame과 Input1의 정보에 차이가 없기 때문이다.

이에 Prev_Frame 위에 Time Shift node를 달아준다. Time Shift node에서 설정해준 Frame 정보에 따라 실제 Frame과 관계없이 아래로 이어지는 Node의 Frame을 정해줄 수 있다.

Time Shift에서의 Frame이 단지 $F으로 설정되어 있다면, 그냥 Input1에서의 정보와 차이가 없기 때문에 $F - 2를 해줌으로 써 이전 Frame의 정보로서의 역할을 하게 만들어준다.

 

잔상을 남기기 위해서는 이전 Frame의 Fog Volume에 현재 Frame의 Fog Volume이 더해져야 한다.

이전 Frame의 결과는 밀도가 낮아진 상태가 됨으로써 더해질 준비가 되어야 하고, 새로들어올 정보는 멀쩡하게 밀도가 높은 상태로 더해질 준비가 되어야 한다.

두 가지의 VDB의 정보를 더해주기 위해서 VDB Combine node를 이용해보자.

Operation을 Add로 두어 두 정보가 합쳐지게 만들어준다. 이때 A Multiplier를 조작해 A로서 들어오는 Prev_Frame의 밀도를 낮춰준다.

 

A Multiplier의 값을 높여주어 잔상이 길게 남도록해주었다.

움직임에 따라 잔상을 남기며, Volume의 영역 또한 커지는 것을 볼 수 있다.

 

이제 Container 정보를 생성하려한다.

Container라는 새로운 정보를 만들어 그 영역 안에서 움직임을 가진 Volume이 존재하도록 만들어주려 한다.

그 전에 먼저 Container 정보에 결합될 temp 정보를 만들어주려한다. 원래의 fog 정보에서 이름만을 temp로 변경해준다.

이후 VDB Combine의 Input1에 container, Input2에 fog의 정보가 들어감으로써 결과적으론 둘이 합쳐진 값은 container의 정보로서 활용되게 된다.

Solver 안에서는 시작과 끝의 정보가 같아야 하기때문에 container의 이름을 fog로 변경해준다.

 

Prev_Frame에서의 Volume과 Input1에서의 Volume을 Bound 시킨 뒤 Merge, 그 후 다시 Bound 시켜주었다.

이렇게 만들어진 Bound는 VDB node에 의해 새롭게 만들어질 container의 Vector Field로서 이용된다.

1. Float의 타입을 가진 Fog VDB의 container 정보를 만들어주었다.

2. container는 오로지 영역의 역할만을 할 예정이기 때문에 밀도가 필요가 없다. Value 값을 0으로 만들어준다.

3. 원래는 VDB Active으로 VDB의 위치 정보를 직접 정해준다. 하지만 미리 만들어둔 Vector Field의 정보가 존재하기 때문에 Reference를 골라 Input2로 들어오는 Vector Field 정보를 불러와 위치 정보로서 이용해준다.

 

Prev_Frame과 Input1 Null node 아래의 node들을 전부 복사해 Solver 안에서 연결시켜주었다.

완성된 Solver node에 Volum Visualization node를 달아 색을 입혀주었다.

이때 Density Scale을 높여줌으로써 색을 더 강하게 만들어줄 수 있다.

 

Source로 들어오는 Object의 조건을 변경해주었다. y축 또한 cos($FF)에 의해 움직이게 만들어주었다.

 

Unpacked Crag를 이용해 Source로 들어갈 새로운 Object를 만들어주었다.

1. Fog VDB로 바로 변환한 결과이다. 부피가 많이 줄어들어 이대로 사용하기 아쉽다는 느낌이 있다.

2. SDF → Polygons → Fog 의 과정을 거친 Fog VDB이다. Convert VDB에서 Isovalue 값을 올려줌으로써 1번에서의 Fog VDB에 비해 덩치가 커진 모습을 볼 수 있다. 앞으로 2번의 Fog VDB 결과를 Source로서 사용해주겠다.

 

이제 Bound의 정보를 이용해 wind라는 Vector Field를 만들면서 Volume이 작동될 영역을 늘려보려한다.

Bound의 Lower Padding과 Upper Padding에 변화를 줘 보겠다. Copy Parameter를 이용하여 정보들을 쉽게 통제할 수 있도록 만들어준다.

Lower Padding과 Upper Padding의 값을 올려줌으로써 원래의 Bound의 크기보다 더 커지는 것을 볼 수 있다.

VDB node로 Vector Float 타입의 wind의 정보를 생성해준다.

VDB Activate에 Input1에 wind, Input2에 Vector Field 정보가 될 Bound를 연결시켜준다.

VDB Activate의 Value를 0, References로 설정해준다.

 

각각의 voxel들이 {0,1,0}이라는 값을 가지고 있어, 마치 위를 향하는 바람처럼 묘사되었으면 한다.

wind와 연결된 VDB Activate 아래에 Volume Vop을 생성해준다.

Constant를 Vector 정보로 변경해 {0,1,0}의 값을 준 뒤 wind 정보(Bind Export)에 연결해주었다.

Volume Trail로 확인해본 결과 위로 향하고 있는 voxel들을 관찰할 수 있었다.

 

이제 {0,1,0}의 값을 가진 Vector Field가 temp에 영향을 주었으면 한다.

VDB Advect를 생성해 Input1에는 temp, Input2에는 wind의 정보를 넣어준다.

VDB Advect의 Timestep 값을 높여준다면 Vector Field 값이 배가 되어 Volume이 위로 향하게 된다.

합성된 temp 정보는 VDB Combine의 input2로 들어가게 된다.

Solver의 결과에서 위쪽 방향으로 이류가 발생하는 것을 확인할 수 있다.

 

만약 위로 향하는 Vector Field의 힘을 더 세게 만들어주고 싶다면, wind의 Volume Vop에서의 Constant 값을 올려주거나 wind의 정보가 이용된 VDB Advect의 Timestep 값을 올려줌으로써 해결할 수 있다.

또한 Voxel Size를 조절해 Detail을 높여주고 싶다면, Source에서의 Voxel Size뿐 아니라 Solver 안에서의 VDB node의 Voxel Size 값 또한 동일하게 조절해주어야한다.

 

바람이 단순히 위로 움직이는 것뿐만 아니라 Noise를 넣어 바람의 흐름이 느껴지게 만들어보려한다.

새롭게 효과를 넣어주는 만큼 다시 세팅을 가볍게 맞춰주도록 하겠다. Voxel Size를 높여준다.

wind에서의 Volume Vop을 수정해주겠다.

Anti-Aliased Noise를 생성한 다음, Constant 값에 Add 해주었다. 이때 Anti-Aliased Noise에 Multiply를 해줌으로써 Noise의 세기를 높여줄 수 있다.

Frequency 값과 Roughness 값 또한 원하는 느낌으로 조절해주도록하자.

만약 Frequency 값이 너무 낮다면 Curl의 길이가 길어져 Noise의 움직임이 잘 드러나게 된다. Noise의 흐름이 보이지 않도록 만들고 싶다면 Frequency의 값을 키워주도록 하자.

Roughness 값이 너무 높다면 Volume이 흩뿌려지는 것처럼 보이게 될 것이기에 적당한 값을 찾아주어야할 것이다.

결과를 본다면 Vector Field 값이 Noise 됨으로써 Advect되는 양상이 달라지게 된 것을 알 수 있다.

 

이제 불과 같은 느낌을 내기 위해 여러가지 Tweak을 해주겠다.

Volume Visualization에서 색을 변경하고 동일한 색의 Emission 값을 준다. 

잔상의 길이가 너무 길기때문에 Timestep값과 VDB Combine의 A Multiplier를 조절하여 길이를 줄여준다.

 

이번엔 Source의 내용을 바꿔보려한다. 수정하기 전 Source와 Solver의 연결을 끊어준다.

Sphere에 Noise를 줌으로써 좀 더 일렁이는 모양의 불덩이를 만들어보려한다. Sphere node 아래에 Attribute Noise를 달아준다.

Polygons의 모양을 변형시킬 예정이기에 Attributes를 Cd가 아닌 P로 변경해준다.

Center Noise 설정을 해준 뒤 Animate 시켜준다.

이제 Amplitude, Element Size, Pulse Duration을 Tweak해 자글자글한 느낌을 만들어낸다.

여기서 좀 더 불꽃이 위를 향하는 느낌을 주고 싶다면, Offset의 y값에 $F를 써넣는다. 이때 $F는 아주 큰 값이기 때문에 $F 뒤에 소수값을 곱해준다.

좀 더 불과 같은 느낌을 내게 되었다.

 

현재 Solver에서 Volume Vop에서 쓰고 있는 Anti-Aliased Noise는 고정되어 있는 Noise이다.

좀 더 불규칙한 느낌을 내기 위해서 Anti-Aliased Flow Noise를 사용해주겠다. 

Vector to Vector 4를 이용해 @P의 정보와 @Time의 정보를 합쳐 Anti-Aliased Flow Noise의 Position 정보로서 활용해준다. Signature를 4D Input, 3D Noise로 변경해준다.

Frequency와 Roughness를 조절해준다.

 

이제 Crag의 망치에 불을 내보겠다.

Unpack으로 압축을 풀어준 뒤, 망치부분만 Blast로 떼어낸다. 다시 Blast로 손잡이부분도 떼어낸다.

 SDF → Polygons → Fog의 과정을 거쳐 Fog VDB로 변환시킨다.

Convert VDB에서의 IsoValue 값을 조절해 망치의 크기를 적절히 키워준다.

Solver에 연결해 결과를 보겠다.

 

지금까지 Sphere를 기준으로 Tweak하였기 때문에 망치에서의 불꽃으로는 느낌이 알맞지가 않다.

망치와 어울리게 Tweak 해주겠다.

Source로 이용되는 Convert VDB의 IsoValue 값을 키워 불꽃에서의 망치부분의 크기를 키워주겠다. 마치 기름에 불이 붙은 것과 같은 느낌을 내게 해준다.

Solver 안에서도 Noise의 세기 및 거칠기, 잔상의 길이 등을 수정해준다.

 

이제 마지막으로 불이 붙은 곳과 붙지 않은 곳에 차이를 주겠다.

불이 붙지 않은 부분의 모양이 정갈하기 때문에 Noise를 먹여 좀 더 리얼하게 만들어주겠다.

Convert VDB 아래에 Remesh node를 달아준다. Target Size를 0.02로 줄여준다.

Remesh 아래에 Attribute Noise를 달아 P에 대해 그 값들을 수정해주도록 한다. 역시 Offset의 y값에만 $F를 기입해준다.

결과를 본다면 확실히 느낌이 거칠어져 좀 더 리얼하게 불과 같은 느낌을 가지게 되었다.

 

만약 Crag의 Animation 중 특정 구간에서 불의 잔상을 길게 남기고 싶다면 Solver 안의 VDB Combine에서 A Multiplier에 Animation을 주도록 하자.

컴퓨터의 속도가 너무 느린 관계로 강의에서 사진을 가져왔다.

 

 

* Tip : 불을 묘사하는 것이 폭발을 묘사하는 것보다 어려운 순간이 올 것이다. 생각보다 불의 일렁임이 빠르기 때문에 빠르게 움직이는 느낌이 없다면, 불보다 연기처럼 보이게 될 확률이 높다.