TWA Houdini1/Volumes

TWA 후디니 1 Volume_04 : 벡터 볼륨 Vol Trail, Gradient, Curvature

yiss09 2023. 2. 22. 05:11

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

 

HOUDINI1_ VOLUMES

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

www.twahoudini.com

 

Volume04는 공부하면서 어렵다고 느껴지는 부분이 많았다. 확실히 집중해서 보도록 하자.

 

1. Vector Volume & How to Visualize

2. Gradient

3. Curvature(곡률)

 


1. Vector Volume & How to Visualize

 

먼저 Volume, Box 그리고 Null을 하나씩 생성해준다.

1. 이때의 Volume의 Rank는 Vector로 정해준다. Node Info로 확인해본다면 vf.x, vf.y, vf.z의 정보를 확인할 수 있다(Volume이기 때문에 float 형태로 정보가 형성된다).

2. Volume의 Size를 3,3,3으로 만들어준다. Box의 사이즈도 똑같이 만들어 template flag를 켜준다.

3. Null의 이름을 volume_control로 만들어준다. 이제 이곳에서 voxelsize라는 이름의 float parameter를 생성해 Geometry 안의 모든 voxel의 size를 Copy Parameter를 활용해 통제해줄 예정이다.

+ Volume의 Initial Value는 {0,0,0}로 설정하며, 이름은 vf(vector field)로 한다.

 

이제 Volume Vop을 활용해 vf(vector field) Volume에 Noise를 줄 예정이다.

1. Bind와 Bind Export를 생성해 vf Volume에 대한 정보를 불러와준다. 이때 vf의 Rank가 vector이기 때문에 Type을 Vector로 설정해준다.

2. Turbulent Noise를 생성한다. 가지고 있는 모든 voxel의 위치 정보에 대해서 Noise를 주기 위해 Vop global에서 @P에 대한 정보를 Turbulent Noise의 position에 연결해준다.

3. 만약 Frequency를 한꺼번에 조종하고 싶다면, Frequency의 x값을 Copy Parameter해 y, z에 Paste Relative References 해준다.

Turbulent Noise는 더해짐으로써 vf Volume의 정보에 영향을 주게 된다.

 

지금까지는 Volume의 밀도를 시각화 하는데 중점을 두었었다. 이제 Volume에서의 vector의 방향을 시각화 해보도록 하자.

1. Volume Trail을 새롭게 이용해보겠다. Volume Trail의 첫 번째 Input에는 point에 대한 정보가 들어가야 한다. 두 번째 Input에는 분석하고 싶은 Volume에 대한 정보가 들어가야한다.

이때 Volume화된 Box를 Scatter하여 만든 points를 첫번째 Input에 넣어주었다.

2. Velocity Volumes에서는 어떠한 Volume을 분석할 것인지 정해줄 수 있다. 이때 vf.x와 같이 분리되어 있는 Volume을 사용한다면 일차원 정보만을 이용하게 될 것이다.

3. Advection Method에서 어떠한 방식으로 Trail을 볼 것인지를 정해주게 된다. 두가지 방법이 있는데, Advect by Distance는 앞으로 점차 나아갈 수 있는 방향을 따라 Trail Lenth 만큼 경로가 표현되는 방식이다. Advect by Time은 주어진 시간에 얼마만큼이나 경로를 따라갈지 묘사하는 방식이다.

4. Trail Length는 Advect by Distance일 때는 선의 길이를 조절해준다는 느낌이면, Advect by Time에서는 길이보다는 시간이 길어진다는 느낌으로 받아들이면 좋다.

5. Maximum 값을 조절해 

 

이때 대각선 방향으로 Trail이 만들어지는 이유는 Turbulent Noise가 0~1 사이의 vector 값을 가지고 있기 때문에 그 평균인 {0.5,0.5,0.5}의 방향으로 line이 생성되기 때문이다.

 

1. Volume Vop에서 Turbulent Noise의 Noise Type을 Alligator Noise에서 Zero Perlin Noise로 변경해주었다. 일정하게 진행하던 방향이 사라지고 난기류와 같이 사방으로 휘는 느낌의 Noise가 발생되었다.

2. Frequency를 0.5로 낮추어 Noise의 구불거림을 줄여주었다.

 

Scatter에서 Force Total Count를 조작해 points의 갯수를 10000개와 200개로 두고 비교하였다.

points가 너무 많을 때에는 정보가 너무 많아 내부의 정보를 확인하기가 어렵고, 반대로 너무 적을 때는 정보를 눈으로 확인하기가 어렵다는 단점이 있다.

 

Scatter에서의 단점들을 해결하기위해 Volume Slice node를 활용해 Volume의 단면을 잘라 시각화해보겠다.

1. 확인하고 싶은 단면을 고를 수 있다. 사진에서는 ZX Plane으로 설정되어 있다.

2. Offset을 조절해 단면의 위치를 움직일 수 있다. 예를 들면, ZX Plane에서는 Y축에 따라 -, + 방향으로 움직이게 된다.

 

 

Volume Trail node가 아닌 Volume Slice node에 display flag를 켜주었다.

Volume의 단면을 확인할 수 있다. 이때 단면에 잘게 쪼개진 각각의 사각형은 실제 Volume의 voxel 사이즈와 동일하다. 이러한 이유로 Scatter와는 다르게 Volume Slice node를 사용한다면 자동으로 voxel size에 맞춰 points의 갯수가 정해진다.

하지만 똑같은 이유로 단점도 발생하게 되는데, Voxel 사이즈가 너무 작아지게 되면, Volume Slice에서 제공하는 point의 갯수가 너무 많아져 불편함이 생기게 된다.

이때는 Attribute Wrangle에서 각각의 point에 random한 seed를 부여해 그 확률에 따라 points를 제거해 그 갯수를 조절해줄 수 있다.

 

Noise와 SDF를 결합해볼 예정이다.

1. 먼저 Rubbertoy를 SDF Volume으로 변경시켜준다.

2. Volume의 해상도에 변화를 주기 위해 Override Bounds를 체크해 범위를 변경해준다. 이는 Rubber Toy가 Volume으로 변환될 때의 영역을 정해주는 역할을 한다.

voxel size는 Copy Parameter를 통해 volume_control과 연결시켜 준다.

 

Curl Noise를 사용하기 전 Noise들이 어떤 느낌으로 사용되는지 알아보겠다.

1. Periodic Noise는 기본적으로 0~1 사이의 패턴이 존재한다. 이는 평균이 0.5라는 경항성을 가지게 한다. 

2. 이와는 다르게 Anti-Alised Noise는 -1~1 사이의 패턴이 들어갔다. 기준을 0으로 하며, 이는 위치정보에 Noise를 줄 때 활용될 수 있다. 하지만 마이너스 값에 의해 Scale, Alpha와 같은 값의 표현에 지장을 주게 된다.

3. Turbulent Noise는 0~1 사이의 값을 가진다. 이는 Anti-Alised Noise의 음수 부분이 접혀 올라갔기 때문에, Scene view 상에서 보다 꽉찬 느낌을 주게 된다. 앞선 Type이 2가지 밖에 없던 Noise들과는 다르게 Type의 종류가 다양하다.

4. Anti-Alised Flow Noise는 Anti-Alised Noise와 Flow Noise를 섞어둔 Noise이다. 해당 Noise는 Type을 따로 정해주는 부분이 존재하지 않는다는 단점이 있다.

5. Curl Noise는 공간상에서 SDF를 Noise와 결합시켜주는 기능을 가지고 있다. 또한 Anti-Alised Flow Noise에서 사라졌던 Noise Type을 다시 설정할 수 있게 되었다.

 

Volume Slice에서 XY Plane으로 변경한 뒤, Offset을 조절해주었다.

Rubber Toy 형상의 Noise와 그 주변을 둘러싼 원래의 vf의 Noise를 확인할 수 있다.

 

Curl Noise가 SDF를 받아들일 때 얼마만큼의 Noise 정보를 생성했는지 확인해보려 한다.

SDF로부터 영향을 받는 Curl Noise를 SDF에 영향을 받지 않는 Curl Noise로 빼준 뒤 그 정보를 vf에 add해준다.

이때 SDF로부터 영향을 받는 Curl Noise의 Surface Effect Radius를 조절해 SDF가 주변에 영향을 주는 범위를 변경해줄 수 있다. 지금은 그 값을 줄여 Rubber Toy 형상만이 보이게 해주었다.

 

이전의 Curl Noise의 형상은 마치 바람이 Rubber Toy를 휘감고 지나갈 때의 모습을 보여준 느낌이다. 하지만 너무 정갈된 느낌이 있어, Noise에 좀 더 Random한 느낌이 들도록 만들어주겠다.

먼저 Volume을 구름의 형태로 만들어준다(volume03에 자세하게 설명되어 있다).

구름과 같이 뭉게뭉게한 느낌을 내준 뒤 Volume SDF를 통해 SDF Volume으로 변환시킨다.

 

SDF Volume을 Curl Noise가 들어간 Volume Vop의 두 번째 Input에 넣어주었다.

Random하게 Curl이 생긴 것을 볼 수 있다.

이때 우리가 얻은 결과는 Volume의 결과로 Volume Vop node로부터 이용이 가능하다. Volume Slice와 Volume Trail은 Volume Visualization과 같이 단지 시각화를 위해 사용되는 node일 뿐이다.

 

 


2. Gradient

 

Rubbertoy를 SDF VDB로 만들어준 뒤 그 단면은 Volume Slice한 모습이다.

현재 Volume Slice는 Infra-Red로 색상이 정의되어 있다. -1~1 사이의 값이 0~1 사이의 값으로 chramp되어 원래 SDF 값이 음수인 부분은 보라색 0이고 값이 커지면 커질수록 빨강색으로 표현되어야한다.

하지만 Scene view에서의 양수값에는 오로지 하늘색만 보이게 되는데, 그 이유는 VDB의 내용이 Band Voxels로 인해 압축되어 초과되는 부분의 정보를 제거하였기 때문이다.

이에 Band Voxels의 값을 높여준다면 묘사할 내용이 늘어나게 된다.

 

SDF 표면이 가지는 노말 정보를 얻기 위해 새롭게 VDB Analysis를 사용해보겠다.

1. Operator에서 VDB를 분석하는 방식을 정해줄 수 있다. Gradient는 scalar 정보를 vector 정보로 변환시켜준다.

2. Output Name에서 Custom Name을 골라 Operator에서 변환된 정보의 이름을 변경해준다.

이제 vector 정보인 gradient를 시각화 해보겠다.

 

Rubbertoy의 표면 방향으로 Volume Trail이 형성되었다.

 

gradient의 느낌을 더 잘 알아보기 위해 Scatter node를 사용해주었다.

Normal과 비교했을 때 비슷한 느낌이 든다.

 

하지만 차이점으로는 gradient의 경우는 실제 표면이 아닌 곳에서도 그 값이 구해지게 된다.

이는 Band Voxels를 올려줌으로써 확인할 수 있었다.

 

SDF는 각각의 voxel로부터 물체의 표면까지의 최단거리의 값이다.

 

toSurface를 각각의 voxel이 SDF을 구했을 때 그 값이 표면을 향하는 벡터로 지정하겠다.

이때 SDF 값이 제각각이기 때문에 toSurface의 값도 제각각이 된다. 이러한 이유로 toSurface를 방향의 정보로서의 가치를 높이기위해 Normalize 하려 한다.

 

toSurface를 각각 DF와 SDF를 활용해 Normalize 한다면 둘은 다른 결과가 나오게 된다.

외부에서 표면을 향하는 vector는 둘의 방향이 같다.

하지만 내부에서의 Normalize는 그 방향이 달라지게 되는데, 그 이유는 SDF가 내부에선 음수 값이기 때문에 표면으로 향하는 원래의 방향과는 반대 방향으로 vector가 움직이기 때문이다.

 

이때 SDF로 나누기 전 (-1)을 곱한 뒤 toSurface를 나누어 준다면 모든 vector가 외부로 향하게 되는 모습을 띠게 된다.

이렇게 만들어진 Gradient는 단순히 표면의 Normal 방향이 아니라, 어떠한 SDF 값이 커지는 그 흐름의 값을 나타낸 것이다.

또한 Graident는 SDF뿐만 아니라, float의 형태로 존재하는 모든 볼륨에 적용 가능하다.

 

만약 온도에 대한 gradient를 만든다면, 온도값이 커지는 방향을 표시해주게 될 것이다.

SDF를 분석해서 구한 gradient가 Normal과 같이 보이는 이유는 안쪽으로 갈수록 음수, 바깥쪽으로 갈수록 양수가 되는 방향을 그리다보니 Normal과 비슷해졌을 뿐이다.

gradient를 normal과 같은 느낌으로 보는 것이 아니라, 어떠한 값이 커지는 방향이라고 인지하고 있다면 새로운 형태의 gradient 또한 더 잘 이해할 수 있을 것이다.

 

기본 Volume으로 SDF를 만든 다음 gradient를 분석해보겠다.

Volume Slice를 통해 만든 gradient는 뭔가 Rubbertoy의 모양을 가지고 있는 듯 하면서 잘 감이 잡히지 않는다.

Scatter에서는 Carve를 활용해 SDF가 커지는 방향으로 선이 나오는 것을 확인할 수 있다.

 

밀도의 Gradient를 확인하기 위해 SDF Volume이 아닌 Fog Volume으로 변경해준 뒤, scatter를 활용한 points를 Volume Trail에서의 points로 사용해주었다.

밀도에서 값이 안으로 들어가면 갈수록 높아지는 것을 gradient를 통해 확인이 가능했다.

 

위의 Gradient의 방향은 SDF가 커지는 방향으로 향하고 있다.

실제 Rubbertoy의 경계로부터 안쪽은 Interior Band Voxels, 바깥쪽은 Exterior Band Voxels에 의해서 정보의 범위가 조절된다.

 

밀도값이 커지는 방향을 Gradient로서 구했다. 보라색으로 되어 있는 안쪽이 밀도가 높은 것을 알 수 있다.

앞으로의 강의에서 Gradient를 쓰겠다는 뜻은, 밀도값이 커지는 방향을 본다고 이해하면 된다.

 

 


3. Curvature(곡률)

 

Curvature(곡률)은 float값으로 곡선을 따라 진행한다고 가정하였을 때, 우회전을 하는 부분을 +, 좌회전을 하는 부분을 -로 둔다. 볼록하게 튀어나온 부분이 +값이 되고, 오목하게 파인 부분이 - 값을 가지게 된다.

Curvature 값은 곡선과 접하는 원의 반지름 즉, r과 반비례한다. 커브가 많이 꺽이게 되면, 접하는 원의 반지름은 작아진다. 반대로, 커브가 완만한 구간에서는 접하는 원이 커지게 된다.

 

먼저 간단한 Sphere를 이용해 Curvature의 기능을 실험해보았다.

Sphere에 Mountain node를 달아 울퉁불퉁하게 만들어주었다.

그 후 Attribute Blur를 달아 급격하게 패인 곳이 사라지게 만들어주었다.

조금 더 디테일한 결과를 얻기 위해 Subdivde로 Mesh를 쪼개주었다.

이제 Sphere의 곡면에서의 Curvature를 구해주기 위해서 새롭게 Measure node를 사용해주었다.

1. 근접한 세 점 사이의 관계를 통해 Curvature를 구해줄 예정이기에 Element Type을 Points로 설정해준다.

2. Measure node에서 어떤 방식으로 측정해줄 것인지를 정해줄 수 있다. Curvature를 골라준다.

3. Principal을 선택해 원칙적인 방식(Curvature 작동 원리)으로 Culvature를 구해주도록 설정해준다.

 

생성된 Curvature값들은 Geometry Spreadsheet에서 확인이 가능하다. 마이너스에서 플러스까지 다양한 값들이 생성되었다.

이를 활용해 Attribute Wrangle에서 @curvature가 0보다 크다면, point들을 제거해주도록 하였다. 볼록한 부분의 mesh가 제거된 것을 볼 수 있다. 이렇게 Attribute Wrangle을 통해서도 Curvature 값을 시각적으로 확인할 수 있다.

 

Curvature node의 활용이다.

Crag를 Unpack한 뒤, VDB 과정을 거쳐 다시 Polygons로 만들어주었다. 이 다음 Remesh를 통해 불규칙적인 mesh를 정렬해주었다. Attribute Blur를 이용해 급격하게 패인 부분을 제거해주었다.

Measure node를 달아 Crag에서의 Curvature 값을 구해주었다.

1. Curvature에 chramp를 해주기 위해 @curvature의 값을 0~1 사이의 값으로 fit 해주었다. 이때 -2~2의 값을 줄여주게 되는데, Curvature의 값은 그 범위가 넓어 적당히 -2~2의 값을 줄여준 것이다.

2. Curvature가 0.5보다 큰 곳은 붉은 색을 작은 곳은 파랑색을 주었더니, 볼록한 부분에 붉은색, 오목한 부분에 파랑색이 칠해진 것을 볼 수 있었다.

 

Curvature를 활용하여 여러가지 느낌의 Crag를 만들어주었다.

Curvature를 어떠한 방식으로 써주어야할지 감이 온다.

 

Curvature를 활용한 Mask 작업을 해볼 예정이다.

Crag 자료를 IsoOffset을 통해 SDF Volume으로 만들어준다.

Measure가 아닌 Volume Analysis를 활용하여 Curvature를 구해주겠다. Name을 달아 sdf로 되어 있던 이름을 curvature로 변경해준다.

 

SDF를 기반으로 분석한 Curvature가 내부를 채우고 있어서 안쪽의 내용을 알아보기 힘들다. Curvature 값에 Fog Volume의 밀도 값을 곱해주어 mask 외부의 0인 부분을 제거해주고, mask 안쪽의 내용만을 보이게 해줄 예정이다.

두 Volume의 합성을 위해 Volume Vop을 이용해준다.

 

Voilume Sample을 이용해 불러온 mask 값을 Curvature에 곱해준다.

Mask 값이 존재하는 밀도 구간에서만 정보가 남아있는 것을 볼 수 있다.

 

Volume Visualization을 활용해 Volume Vop의 결과에 색을 주려 한다.

1. 이전의 fit function에서 사용하였던 -2~2 사이의 값을 그대로 사용해준다.

2. Scene View에서 흰 배경이 생긴 이유는 Density Ramp에 의해서 0의 밀도에 위치해 보이지 않아야 할 값들이 0.5의 값을 얻게 됨으로써 모습을 보이게 되었다.

3. Diffuse Ramp를 조절해 색을 주었다. 이때 Diffuse Range의 값은 Minimum,Maximum 값으로부터 Copy Parameter 해주었다.

 

1. Geometry Spreadsheet을 확인해보면 Curvature 값이 높게 나오는 경우가 있다. 이러한 경우를 전부 통제하기 위해서 Min, Max 값에 -100, 100을 주었다.

2. Density Scale을 조절해줌으로써 색을 진하게 만들어줄 수 있다.

3. 앞서 0.5의 값을 가져 보였던 부분의 값을 0으로 낮춰 주었다. 또한 색 표현을 위해 0을 제외한 음수값 양수값을 모두 볼 수 있게 해주었다.

4. Diffuse Ramp를 조작해 그럴듯한 색을 띠게 만들어주었다.

 

만약 이때 Mask를 Curvature에 곱해주지 않는다면 어떻게 될까?

당연히 Curvature의 값만을 Visualization해주기 때문에 Curvature의 모습과 같은 것을 볼 수 있다.

이때의 결과로 알 수 있는 점은 Volume에서의 Curvature Field는 SDF가 같은 곳 IsoValue가 같은 곳에서의 Curvature 값들을 보여주는 Volume 공간이라는 점이다.

 

Curvature와 같은 No mask의 결과와 Iso Surface에서의 형태가 비슷한 것을 볼 수 있다.

이때의 Iso Surface는 Offset을 높여주었다.

 

마지막으로 Mask 아래에 Attribute Wrangle을 달아, Clamp 해준다면 chf을 통해 Mask의 세기를 조절해줄 수 있다.

 


역대급으로 너무너무 힘든 파트였다.

강의로 들을 때는 잘 넘어갔지만, 공부일지를 작성하면서 이해가 잘 안되었던 부분들이 많았다.

완전히 이해할때까지 반복하다보니, 평소보다 4배는 많은 시간이 걸렸다... 정말 너무너무 힘들었던만큼 까먹지 않았으면 좋겠다.