아는분의 제안 겸 조언으로 '투명한 물' 구현을 해보았다.

원래는 '언어나 프로그램 제약없이 할수 있도록' 다이렉트X를 추천받았으나...

하도 진행을 못하는걸 보고는 그냥 다른 엔진 써보고 해서... 원래 잡던 유니티 말고 언리얼엔진 처음 열어서 구현했습니다.

 

 

일단. 뭘 만들었는지는 영상부터 보고 갑시다.

 

(영상은 개선판입니다)

 

투명한 물, 물 표면 표현, 굴절, 반사 가 들어간 기본적인 물 표현입니다.

 

 

 

* 해당 자료 구현시 Pub Games의 영상을 참고하였습니다.


 

전체 구조도입니다.

 

아는건 별로 없지만, 까먹지 않기 위해서라도 하나씩 정리해봅시다.

* 틀린게 많을 수 있습니다. 틀린것이 있다면 지적바랍니다.

 

1. 포지션

 

1) 절대 월드 포지션 (Absolute Absolute world position) :

이 텍스쳐 구현에서 월드 포지션을 사용하는 목적은 텍스쳐가 적용된 오브젝트의 '위치에 무관하게' (=동일한 위치에) 텍스쳐가 적용될 수 있도록 하는 목적으로 사용된다.

즉, 텍스쳐 표현을 절대 월드 좌표로 고정해버림으로써, 오브젝트가 이동하더라도 텍스쳐 표현이 동일한 위치에 적용된다.

 

뭐 이렇게 쓰니 같은말 두번 쓴거같은데요... 표현 기준이 오브젝트 별 이 아니라 오브젝트가 놓인 월드 좌표계 기반이다... 정도면 될거같습니다.

 

(자료 참조)

 

2) Divide? :

값을 나누는 이유는... 자체 그림자 방지 (To provide a fall off to the self shadowing)를 위해서라는데... 아직 잘 이해가 안되는 부분이네요.

여긴 공부가 더 필요할것 같습니다.

나누는 값 자체는 텍스쳐를 적용할 오브젝트의 사이즈 만큼... 이라고 하는거 같네요.

 

3) Mask :

R은 X축, G는 Y축, B는 Z축으로 표현되는 모양이더라구요.

그리고 UE4에서는 Z축이 높이를 의미하기 때문에... 평면 가로/세로의 값만 중요하여 두 값을 추출하기 위해 R,G 마스크를 사용한다... 고 하는것 같습니다. 즉, 'XY 평면에 평행한 텍스쳐를 구현하기 위해 X,Y 값만 추출한다.' 고 볼수 있겠네요.

월드 포지션에는 당연하겠지만 3개의 값이 들어갑니다. X축, Y축, Z축.

사용한것은 ComponentMask였으며, 적당히 축약어로 검색해도 잘 튀어나옵니다.

축약어 사용 예

 

2. 노멀맵

'노멀맵' 자체에 대한 설명은 검색해보시거나 들고계신 책 보는게 빠르고... (사실 이해 덜했음)

이 텍스쳐에서는 어떻게 써먹고 있나 봅시다.

 

 

1) Panner : Panner를 사용하는 이유는 단순하지만 큰 이유입니다. 물이 흐르는것을 표현하기 위해 텍스쳐를 움직여줘야 하기 때문이죠.

텍스쳐의 U (가로) / V (세로) 를 조합한 방향으로 움직여 복잡한 애니메이션이 일어나는것처럼 보이는 목적입니다.

레퍼런스 참조 하시면 더 좋습니다. 넹.

input은 월드 좌표계였습니다.

 

2) Texture Sample : 말할것도 필요없는 노멀맵입니다.

위 아래의 텍스쳐가 조금 다른것처럼 보이는데, 사실 두개 같은거에요. 그냥 복사 - 붙여넣기 한것.

텍스쳐에서 '질감'을 표현해주는 노멀맵을 가져와서 적용시킨것입니다.

두개인 이유는 물 흐르는 표현을 2개로 겹쳐서 그런것이고... 사방에서 퍼지는걸 하고싶으시다면 Panner를 포함해서 4개를 넣으시면 되겠습니다.

 

3) Add? : 말도 필요없이 그냥 만들어진 Panner - Texture 세트를 합치는 목적입니다.

그래야 한번에 출력되죠.

 

4) Constant 3 Vector : 솔직히 얘가 제일 이해가 안갑니다.

기능 자체는 '3채널 상수값'을 벡터 형식으로 출력해주는것이 전부입니다.

3채널을 사용하는 텍스쳐 좌표 변경시 사용하는것이 좋다는데...

잠깐 찾아보니 실행 직전에 한번 계산되고, 플레이 도중에는 변경이 불가능한 마테리얼 인스턴스. 라고 하네요. 

근데 만일, 물이 튀기는 표현등을 넣는다면... Dynamic 값을 이용해야하지않을까 싶네요.

이것도 레퍼런스 참조해보시면 더 도움이 될것 같습니다.

 

5) Multiply : 움직임이 구현된 Texture 와 인스턴스 값을 곱해서 적용시키는 목적입니다.

더하면 단순히 수치만 고정되는것이고, 곱하게 되면 각 R/G/B값에 해당되는 수치가 곱해져 계산이 되겠네요.

 

여기까지 붙은것을 마테리얼 파라미터의 Normal에 고정시켜줍니다.

 

이러면 물 표면 표현이 완성됩니다.

 

 

3. Opacity (투명도)

1) Depth Fade : 말그대로 '깊이별 Fade' 입니다. 인자로는 투명도 값과, Fade가 시작되는 월드좌표 수치를 받네요.

2) Fresnel (프레넬) : 실제로는 '관찰자가 바라보는 각도에 따라 반사되는 빛의 세기가 달라지는 현상을 설명하는 데 사용되는 용어', 즉 반사와 관련된 값인데요...

물의 투명도는 Fresnel값 계산과 반대로, 수직으로 보면 투명하고, 평행하게 될수록 덜 투명하게 보여야 합니다.

그래서 Fresnel값에 1-X를 해줘서 값을 뒤집는것이구요.

이를 곱해서 Fresnel에 따라 Fade가 일어나도록 구현이 됩니다.

 

4. Reflection (반사)

사실 구현하면서 제일 골치아프게 했던 부분인데요...

구현 자체는 금방했으나, 반사값을 너무 크게 하는 바람에 카메라 사이즈(= 스크린 사이즈)만큼의 사각형 격자처럼 반사가 일어나는 참사가 일어나기도 했습니다.

 

구현자체는 2시간만 걸렸으나 이거 원인 찾는데 3시간 넘게 써버려서 총 작업시간이 6시간 언저리로 만든 원흉...

대충 이렇게 말이죠.

 

뭐. 지금은 수정이 되었습니다.

 

 

 

 

반사값 파라미터는 딱히 뭐 더 없습니다.

Depth Fade 값에 반사 수치 인자를 곱해줘서 그걸 Reflection 파라미터에 넣어주면 끝입니다.

그냥 값 조절 잘 하십시오. 말고는 할말이 없네요. 넹

 

5. Base Color

 

 

Fresnel에 붙어있는 Normal Map 값은 아까 만들었던 그 Normal Map 값입니다.

 

1) Color : 말그대로, 밝은 면 / 어두운 면의 컬러링입니다. 큰 차이는 없지만, 색상이 변경되면 차이가 있긴 하더라구요.

원하신다면 저 값을 녹색이나 보라색 등으로 바꾸면 독물이 되어버리는 진기한 현상을 목격하실 수 있습니다.

 

2) Lerp (Linearly interpolate, 선형 보간) :

네. 선형대수 시간에 나오던 그 선형보간입니다. 단순히 선형보간 짧게 설명하자면 A / B 점을 가지고 중간의 임의의 값을 뽑아내기 위한 방법인데요. 왜 갑자기 여기서 쓰이느냐.

컬러가 2개밖에 없잖아요? 근데 자연스러운 컬러링을 위해서라면 범위에 따라 색상이 자유롭게 바뀌어야하니... 그때 적용이 되어서 들어가는 셈입니다.

그래야 약간 깊이, 더 깊은곳 등등에서 색이 자연스레 들어가는것이겠죠.

이를 Depth Fade 값과 곱해줌으로써 Depth 값에 따라 적용이 되도록 해줍니다.

 

3) Diffuse (디퓨즈) :

일반적으로 Diffuse Map은 물체의 입체감, 깊이감, 색을 부여해주는 요소인데...

단순하게 설명하자면 텍스쳐의 색감과 질감을 나타내주는 요소라고 할 수 있겠다.

사실 이쪽도 아직 이해가 부족해서... 다른 자료를 찾아보시는걸 추천한다.

 

아무튼 이 값은 마테리얼 파라미터의 베이스 컬러에 고정시켜줍니다.

 

이로써 4가지 항목 (노멀맵, 베이스 컬러(=디퓨즈 맵), 리플렉션, 투명도)를 모두 적용시켰다.

 

그렇게 나오는 마테리얼 결과값은 아래와 같다.

(실제로는 움직입니다)

잘 보면 투명도, 반사등이 적용되어있는걸 볼 수 있다.

 

이걸 물 표면에 적용시켜주면 위 영상과 같은것이 나오게 되는것.

 

단순히 영상 하나를 참고해서 야매로 만든것인데, 다음에는 좀 공부를 해서 물리가 들어간 물 구현도 해봐야 할 듯 싶다.

+ Recent posts