# AI 꾸러미 — 툰 물 (기슭 거품 테) — Toon water (stylized water)
> 물 셰이더가 섬 높이 식을 그대로 알아 물 깊이를 구해, 깊이로 색 3단을 끊고 기슭 거품 띠 · 배 뒤 V자 물거품 · 바위 둘레 고리를 그린다.  
> 견본: https://ai-techstudio.web.app/#t/i222

이 문서를 코드 도우미(Claude Code · Cursor · ChatGPT 등)에 그대로 주면 돼요. 「## 주문서」 가 할 일, 나머지는 참고 자료예요.

## 주문서

### 만들어 줘: 툰 물 (기슭 거품 테) — Toon water (stylized water)

#### 1. 목표
섬이 있는 바다 퍼즐에 툰 물을 넣어 줘 — 깊이 색 3단 · 기슭 거품 테 · 배 물거품까지, 그림체는 밝은 툰 (3단 + 외곽선).

#### 2. 핵심 기술 용어
- **Toon water (stylized water)** — 만화풍 물 — 깊이 색 계단 + 하얀 거품 테
- **Shoreline foam from depth** — 물 깊이가 얕은 곳에 거품 띠
- **Analytic depth (shared height function)** — 땅 높이 식을 셰이더에서도 써서 깊이 구하기
- **Boat wake (V-shaped)** — 배 뒤로 벌어지는 V자 물거품

#### 3. 환경
- 플랫폼: three.js r186 (ES 모듈 · TypeScript, `import * as THREE from "three"`), WebGL2, 외부 라이브러리 추가 없이
- 화면: 3D · 브라우저 — PC 와 폰(가로 844×390 · 세로 390×844) 모두, 60fps 목표

#### 4. 조건
- 땅 높이 식을 TS 와 GLSL 에 똑같이 — 섬 자료는 uniform vec4 배열(x, z, 반지름, 높이)로 넘긴다
- 툰 색은 step 계단 (0.16 · 0.42), 매끈 모드는 smoothstep — 단추 하나로 바꿀 수 있게
- 기슭 거품은 깊이 < 거품 폭 (툰은 step, 매끈은 smoothstep), 폭은 시간으로 살짝 숨쉬기
- 섬 · 야자수 · 배는 툰 3단 + 외곽선 껍데기 (외곽선은 카메라 거리로 굵기 보정)
- 물 판은 한 장(PlaneGeometry 60 × 40, 1 × 1) — 정점을 쪼갤 필요 없다

#### 5. 완성 기준 (이게 보이면 성공)
- 섬 둘레로 얕은 청록 → 중간 → 짙은 파랑 세 띠가 또렷이 보이고, 물가에 흰 거품 테가 살랑인다
- 거품 테 바깥으로 고리 줄이 퍼져 나가 사라진다
- 배가 지나가면 뒤로 V자 물거품과 가운데 꼬리 거품이 생기고, 바위 둘레에 거품 고리가 생긴다
- 「툰 단계 물」을 끄면 매끈한 그러데이션으로 바뀐다

#### 6. 진행 방식
- 핵심 코드 위주로, 설명은 짧게. 내 프로젝트에 끼워 넣기 쉬운 함수 · 클래스로 나눠 줘.
- 처음 화면에 바로 결과가 보이게, 그리고 켬/끔(또는 전/후) 비교를 할 수 있게 만들어 줘.
- 그림 · 소리 · 모델 파일이 필요하면 코드로 만든 임시 대체물로 먼저 돌아가게 하고, 진짜 파일로 바꿀 자리를 표시해 줘.
- 마지막에 「확인 방법」(무엇을 보면 성공인지)과 「조절할 값」 목록을 짧게 정리해 줘.
- 답변과 코드 주석은 한국어로 해 줘.

## 원리
- 땅(섬) 높이를 식 하나로 만든다: 기본 -0.6 + 가우스 언덕 4개 + 잔 굴곡. 같은 식을 물 셰이더에 uniform 배열로 넘긴다.
- 물 위 픽셀마다 그 식으로 땅 높이를 다시 계산하면 물 깊이 d = -H(x, z) 를 바로 안다 (깊이 버퍼가 필요 없다).
- 툰이면 깊이로 색을 끊는다: 0.16 아래 얕은 청록 · 0.42 아래 중간 · 그 너머 짙은 파랑. 잡음으로 경계를 조금 흔든다.
- 깊이가 거품 폭(0.12)보다 얕으면 하양 — 기슭 거품. 바깥으로 퍼지는 고리 줄 · 배 뒤 V자(옆 거리 ≈ 0.08 + 뒤 거리 × 0.32) · 바위 둘레 고리를 더한다.

## 핵심 코드 — 높이 식으로 깊이 → 색 3단 · 기슭 거품 · 퍼지는 고리
(발췌: demos/lib/toonIsle.ts makeToonIsle() 물 조각 셰이더를 정리)
```glsl
// noise() 는 이 위에. uIsl[i] = (x, z, 반지름, 높이) — TS 의 ISLANDS 와 같은 값
uniform float uTime, uFoam, uToon; uniform vec4 uIsl[4];
uniform vec3 cShallow, cMid, cDeep, cFoam;
varying vec3 vW;
float H(vec2 p){
  float h = -0.6;
  for (int i = 0; i < 4; i++){ vec4 s = uIsl[i]; vec2 d = p - s.xy; h += s.w * exp(-dot(d, d) / (s.z * s.z)); }
  return h + 0.07 * sin(p.x * 1.7 + p.y * 0.9) * cos(p.y * 1.3 - p.x * 0.4);
}
void main(){
  float d = -H(vW.xz);                                   // 물 깊이
  float n = noise(vW.xz * 2.4 + vec2(uTime * 0.3, uTime * 0.2));
  float dd = d + (n - 0.5) * 0.08;                        // 경계를 조금 흔든다
  vec3 col = uToon > 0.5 ? (dd < 0.16 ? cShallow : (dd < 0.42 ? cMid : cDeep))
                         : mix(cShallow, mix(cMid, cDeep, smoothstep(0.25, 0.6, dd)), smoothstep(0.02, 0.3, dd));
  float edge = uFoam * (0.8 + 0.2 * sin(uTime * 1.8 + n * 5.0));
  float foam = uToon > 0.5 ? step(dd, edge) : 1.0 - smoothstep(edge * 0.5, edge, dd);
  // 거품 테 바깥으로 퍼지는 고리 줄
  float ph = fract(uTime * 0.33);
  float ring = uFoam * (1.35 + ph * 1.8);
  float line = (1.0 - smoothstep(0.012, 0.03, abs(dd - ring))) * (1.0 - ph) * step(0.42, noise(vW.xz * 3.2 + 7.0));
  col = mix(col, cFoam, clamp(max(foam, line * 0.95), 0.0, 1.0));
  gl_FragColor = vec4(col, 1.0);
  #include <tonemapping_fragment>
  #include <colorspace_fragment>
}
```

## 흔한 실수 · 확인 목록
- [ ] **TS 의 땅 높이 식과 셰이더 식이 조금이라도 다르면 거품이 물가에서 떨어져 뜬다** — 같은 식 · 같은 값을 쓴다. 섬 자료는 배열 하나에서 둘 다 읽게.
- [ ] **외곽선 껍데기를 물 판에 붙이면 지저분하다** — 물 · 얇은 판에는 외곽선을 붙이지 않는다 (툰 규칙).
- [ ] **툰 장면에 톤 매핑을 켜 두면 3단 색이 흐려진다** — 툰 장면은 NoToneMapping 이 기본, 색은 빛 세기로 맞춘다.

## 완성 기준 체크리스트
- [ ] 섬 둘레로 얕은 청록 → 중간 → 짙은 파랑 세 띠가 또렷이 보이고, 물가에 흰 거품 테가 살랑인다
- [ ] 거품 테 바깥으로 고리 줄이 퍼져 나가 사라진다
- [ ] 배가 지나가면 뒤로 V자 물거품과 가운데 꼬리 거품이 생기고, 바위 둘레에 거품 고리가 생긴다
- [ ] 「툰 단계 물」을 끄면 매끈한 그러데이션으로 바뀐다

## 이 기술 정보
- id: `i222` · 분류: 그래픽 · 셰이더 › 셰이더 · 3D · 난이도 보통 · 폰 부담 보통 (폰 주의) — 물 픽셀마다 높이 식(언덕 4개 반복) + 잡음 약 6번 + 바위 4개 반복. 깊이 버퍼를 따로 안 그려 오히려 가볍다.
- 라이브 견본 (브라우저에서 직접 조작): https://ai-techstudio.web.app/#t/i222
- 쓰면 좋을 때: 섬 · 땅 높이를 식으로 만든 툰 장면 / 깊이 버퍼를 따로 그리기 싫을 때 (폰) / 배 · 바위가 있는 바다 퍼즐
- 쓰지 말 때: 땅이 식이 아닌 모델(메시)일 때 — 대신 깊이 텍스처로 깊이 차 / 사실적인 물 — 대신 흐르는 강물(u22)

## 견본 실제 코드 (라이브 견본이 돌리는 코드 — three.js · TypeScript)
### i222 견본 항목 — `src/demos/demosLook2.ts:4506`
```ts
  i222: { kind: '3d', caption: '물 셰이더가 섬 높이를 알아 물 깊이로 색 3단 + 기슭 거품 띠 · 배 뒤 V자 물거품 · 바위 둘레 고리 — 섬 · 야자수 · 등대 · 배는 명암 3단 + 외곽선', make: () => makeToonIsle() }
```

## 관련 기술
- 먼저 알면 좋은 기술: [툰 셰이딩 (3단 명암)](https://ai-techstudio.web.app/ai/t/u01.md) `u01` · [흐르는 강물 셰이더](https://ai-techstudio.web.app/ai/t/u22.md) `u22`
- 다음에 해 볼 기술: [외곽선 (뒤집은 껍데기)](https://ai-techstudio.web.app/ai/t/u02.md) `u02` · [정점 흔들기 (바람 · 물결)](https://ai-techstudio.web.app/ai/t/i13.md) `i13`
