# Part 21 | 물 만들기

**물의 특징**

* 바닥이 보이게 투명해야 한다
* (환경을) 반사해야 한다
* 빛나야 한다
* 굴절되어야 한다
* 흘러가야 한다
* 육지와 맞닿는 면이 투명하거나 포말이 생겨야 한다

## 02 기본적인 물 효과 만들기

![](https://velog.velcdn.com/images/biomatrix117/post/ecac7941-783c-4086-b29e-0f3d3c40d03b/image.png)

* Waterbump 노말 텍스쳐를 Cubemap 텍스쳐의 Normal에 연결시킨다
* 이 결과를 Base Color에 넣으면 그나마 자연스럽지만, 책에선 Emission에 일단 넣긴 함.

![](https://velog.velcdn.com/images/biomatrix117/post/53807ab0-cefa-47fd-a5c3-fe6fa439847b/image.png)

* Base Color를 검은색으로 바꾼다
* Normal Strength 노드로 노말맵의 강도를 낮춘다
* 타일링을 2x2로 증가시킨다
* Transparent로 바꾼다
* water에 사용된 plane의 Inspector > Lighting > Cast Shadows > Off

![](https://velog.velcdn.com/images/biomatrix117/post/98cac88a-e263-47a6-808f-b139fc1baf62/image.png)

주변과 어느 정도 어울리는 반사로 만들어주기 위해, 주변 환경을 캡처하여 정반사 소스로 만드는 리플렉션 프로브를 사용한다.

* GameObject > Light > Reflection Probe를 만든 후 씬의 중앙에 놓는다
  * 땅에 묻히거나 오브젝트 안에 위치시키면 안된다. 리플렉션 프로브는 그 위치에서 사방을 촬영하는 카메라라고 생각하면 된다.
* 리플렉션 프로브를 선택하고, Edit Bounding Volume > 캡쳐가 되길 원하는 배경이 충분히 들어갈만큼 크기를 조절한다
  * 이 영역에 들어가지 않는 오브젝트는 촬영되지 않으며, 빈자리는 스카이 박스로 채워진다.
* 리플렉션 프로브에 촬영되길 원하는 오브젝트들을 선택하고, Inspector에서 Static 옆 화살표 클릭하고 Reflection Probe Static을 활성화
* Bake한 후 큐브맵 대신 Reflection Probe를 꺼내어 연결한다.

![](https://velog.velcdn.com/images/biomatrix117/post/2c4dbb4e-f405-4947-961a-a9c5b3b22111/image.png)

모든 물체, 특히 비금속 물체는 시야 기준으로 기울어질수록 반사가 심해진다. 물도 마찬가지다.\
프레넬로 이를 구현할 수 있다.

* Fresnel Effect를 꺼내어 Alpha에 넣어주고, Power를 조절한다.
  * 내려다보는 바로 아래 각도는 많이 투명해지고, 시야각과 멀어지는 부분에선 투명도가 거의 없어지고 반사가 심해진다.
* Fresnel Effect를 Lerp로 반전시킨 후에 Normal Strength에 넣어준다.
  * 노말의 강도가 시야에서 멀어지면 옅어지고 플랫해진다.

![](https://velog.velcdn.com/images/biomatrix117/post/c65e47ba-1db3-454e-8bb9-ac6d7a56e8e6/image.png)

제자리에서 찰랑거리는 물은 각기 다른 방향으로 움직이는 normal 텍스쳐를 blend하면 간단하게 구현할 수 있다.

## 03 물 표면 웨이브 만들기

**Sine Wave 만들기**

![](https://velog.velcdn.com/images/biomatrix117/post/a17df719-4e59-4f3f-9b83-1984186ba439/image.png)

y 위치를 x축 위치에 대응되는 sine값으로 치환하면 이런 모양이 나온다.

![](https://velog.velcdn.com/images/biomatrix117/post/8a3df839-9000-458c-8410-cd677c81922b/image.png)

파장의 길이와 높이 수치를 조절하고, sine에 대입할 x축 위치에 시간을 더해서 흘러가게 만든다.

![](https://velog.velcdn.com/images/biomatrix117/post/9137972e-678c-4a7b-8ba9-51e4bd0bcaca/image.png)

* 아직 노말 벡터는 굴곡대로 계산되고 있지 않고 y축 방향만 가리키고 있었다
* 미분해서 cosine으로 바뀌고, Y축 높이가 곱해지는 만큼 똑같이 곱해준 뒤, X축 방향에는 원래 탄젠트였던 1을 넣고, noramlize하면 Tangent 벡터가 된다.
* Z축 벡터인 (0,0,1)와 외적하면 Normal 벡터가 된다.

**Gerstner Wave (거스너 웨이브) 만들기**

![](https://velog.velcdn.com/images/biomatrix117/post/c8d87bc2-1a7e-4705-bb80-8f01d0deaece/image.png)

Gerster Wave는 sine wave보다 좀 더 그럴듯한 품질을 가진 파도를 표현할 수 있다.\
X좌표를 cosine으로 이동시켜 뾰족한 모양의 파도를 만든다.

* X를 따로 떼어낸 뒤, 이전에 계산했던, 시간에 따라 달라지고 파장과 높이를 조절했던 X좌표를 cosine에 넣은 뒤 더해주고 다시 X 좌표에 넣는다.
* x와 y의 미분값을 통해 Tangent를 구하고, Tangent로 Normal을 구한다 (사진 생략)

> **의문해결**\
> 이렇게 하면 X가 움직여야 하는거 아닌가 했는데, 움직이는게 맞았다. 끝 부분 보니까 생겼다가 사라지는 부분이 생긴다. 0.09를 곱해주기 때문에 변동폭이 크지 않았고, 삼각함수라 순환하기 때문에 쭉 가지 않아서 그랬던 것.

![](https://velog.velcdn.com/images/biomatrix117/post/b567f89c-61ce-4ca9-885e-04b99685fd23/image.png)

거스너 웨이브를 서브 그래프로 만들고, 이전에 만든 물과 합친다.

## 04 굴절

![](https://velog.velcdn.com/images/biomatrix117/post/75a8f1a4-376a-429e-b601-53c5b192836d/image.png)

이전에 했던 것처럼

* Base Color를 검은색으로 만들고
* Scene Color에 Scene Position를 연결하고 Emission에 넣어주면 투명해진다

![](https://velog.velcdn.com/images/biomatrix117/post/787f5cec-cf30-46cf-9f8d-0a741da8ba34/image.png)

물에 사용했던 노말맵에 아주 작은 값을 곱해서 Scene Position에 더해주면 굴절이 일어난다.\
이렇게 하면 물에 잠긴 하반신 뿐 아니라 상반신 뒤에도 굴절이 일어나는데, 해결하려면 물에 잠긴 부분을 구분하는 복잡한 과정이 필요해서 보통 여기까지는 해결 안 한다.

## 05 뎁스(Depth)를 이용한 투명과 깊이

물은 깊어질수록 불투명해지고, 땅과 맞닿는 부분은 투명하다.

![](https://velog.velcdn.com/images/biomatrix117/post/6b6aa70c-baac-4838-912f-ad26e147f687/image.png)

Depth Fade를 이용해서 경계면을 부드럽게 만든다.

![](https://velog.velcdn.com/images/biomatrix117/post/f7a3df2c-7d01-4b7c-b40c-d1d061df366f/image.png)

기존 셰이더에서 Alpha 값에 Depth Fade를 넣어주면 경계면 부분이 부드럽게 연결된다

![](https://velog.velcdn.com/images/biomatrix117/post/715f7bfb-a29a-418f-8b90-9c504b176fca/image.png)

* Depth Fade로 지면과 가까운 부분(0에 가까움)과 물이 깊은 곳(1에 가까움)을 나누고, 그걸 Lerp에 넣는다.
* Lerp로 지면과 가까운 부분은 Scene Position과 Scene Color로 투명하게 표현된 부분이 드러나게, 물이 깊은 곳은 Color 단색이 드러나게 한다.
* Fresnel 효과로 또 다시 Lerp하여 이전에 구현했던, 지면과 가까운 부분의 굴절이 심해지는 효과와 합쳐준다.
* (삽질) 왜인지 모르겠는데, 결과를 Smoothness에 넣어놓고 왜 색깔이 이상하게 보이지? 이러고 있었다.

## 06 마무리와 응용

**Unlit으로 변환하기**

원래 Lit 셰이더에 있던 Metalic이나 Smoothness는 하나도 사용하고 있지 않는데 들어가 있다.\
사용하지도 않는 연산이 가동 중이니, 깔끔하게 Unlit으로 만들어준다.\
대신 Specular는 나중에 더해줘야 함.

**Alpha 사용하지 않게 만들기**

Depth Fade를 Alpha에 연결해서 투명도를 만드는 건 옳지 않다.\
이미 Scene Color를 통해 투명도를 표현하고 있기 때문.\
여기에 다시 Alpha를 이용해서 추가로 투명하게 할 필요가 없다.

그런데 Depth Fade를 통한 투명도를 알파 블렌딩으로 표현하면 굴절된 다리와 투명도로 인해 굴절되지 않은 다리가 겹쳐서 2개로 보이게 된다.

앞서 이미 물 깊이에 따른 투명도를 만들면서 투명도처럼 보이는 불투명 기능을 다 만들어놓았기 때문에, 이전 결과물에서 알파를 끊어주기만 하면 된다.

이렇게 되면 다리는 굴절되는데 Depth Fade는 굴절되지 않는다. Depth Fade도 다리와 같이 굴절되게 만들어야 한다. 이를 위해 굴절 연산을 적용한 Screen Position 값을 Scene Depth의 UV에 넣어준다.

**응용 및 마무리**

![](https://velog.velcdn.com/images/biomatrix117/post/f56f8aee-5630-46f9-8fa9-d4e647cd5e47/image.png)

스페큘러가 없기 때문에 추가해주고

![](https://velog.velcdn.com/images/biomatrix117/post/87156ed9-6e41-4330-9d81-44c5300d9fb7/image.png)

Transparent라 로봇까지 그린 후 Screen Color를 받아오기 때문에, 물 밖의 로봇도 같이 굴절되는 현상이 일어난다.

Comparison 노드로 Depth Fade가 0보다 크냐 작냐를 통해 물보다 카메라에 가까이 있다면 굴절 없이 그냥 그려준다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lazyartisan.gitbook.io/note/main-page/books/urp/part-21-or.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
