Files
blub-blub/assets/shaders/water.gdshader
T
ttipo 519e4980de 먼 바다 배경·하루의 빛·층 구조·감상 모드
네 가지 작업이 같은 함수들을 겹쳐 고쳐서 한 커밋으로 묶는다.
쪼개려면 hunk 단위로 갈라야 하는데 서로 얽혀 있어 오히려 위험하다.

먼 바다 배경 (backdrop.gd)
- 3/4 부감에서 화면 위쪽은 더 먼 곳이다. 거기까지 모래를 깔면
  바다가 아니라 사막처럼 보여서, 위쪽 띠를 물로 비웠다.
- 먼 물 그라디언트 → 능선 → 먼 실루엣 순으로 깊이를 만든다.
- Seabed가 뒷줄일수록 색을 물빛 쪽으로 당겨 공기원근을 준다.
- 빛줄기를 알파를 더하는 방향으로 바꿨다. 걷어내는 방향이면
  바닥만 밝아지고 물기둥은 텅 빈 채로 남는다.

하루의 빛 (day_cycle.gd)
- 실제 시각에 맞춰 새벽/아침/낮/저녁/밤. 이름은 구간으로 끊고
  색과 밝기는 계속 보간한다.
- 밤에는 물결과 빛줄기가 잦아들고, 스스로 빛나는 것은 어둠을
  되밀어 오히려 도드라진다.
- godot --path . -- --hour=21 로 특정 시각을 눈으로 확인할 수 있다.

한 화면에 한 층
- 가로 연속 스크롤을 버리고 층 전환으로 바꿨다. 위층(얕은 바다)에서
  아래층(열수구)으로 내려간다. 층 선택기·휠·↑↓ 키.
- 층은 내부적으로 여전히 옆으로 늘어서 있고 화면이 한 구간만 비춘다.
  갈아탈 때만 세로로 미끄러뜨려 깊이가 위아래로 읽히게 했다.
- 칸 크기를 가로에서 정하도록 뒤집고 ZONE_COLUMNS를 36으로 올렸다.
  층당 칸이 96 -> 216이라 정원과 해금 곡선은 다시 봐야 한다.
- 한 화면에 한 층만 보이므로 층 색은 이웃과 섞지 않는다.

감상 모드 (F11)
- 창을 화면 전체로. 세로로 남는 공간은 격자가 아니라 물기둥에 준다.
  격자를 키우면 타일만 커지고 보이는 열은 오히려 줄어든다.
- 창을 화면과 픽셀까지 똑같이 맞추면 Windows가 독점 전체화면으로
  승격시켜 size 지정이 먹지 않는다. usable_rect까지만 쓴다.

그 밖에
- 저장 window_state: scroll_x -> layer
- 알림이 정보 바와 겹치던 것을 바 아래로 옮겼다
- 난파선 선체 폴리곤이 제 몸을 가로질러 삼각분할이 실패하던 것 수정

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 12:41:36 +09:00

54 lines
2.7 KiB
Plaintext

shader_type canvas_item;
// 탑다운 바다의 물빛 오버레이. 바닥 위에 덮여서 "물을 통해 내려다본다"는 느낌을 만든다.
// 구역 하나를 담당하고, 좌우 끝 색을 이웃과 공유해 이음매 없이 이어진다.
uniform vec4 tint_left : source_color = vec4(0.27, 0.70, 0.80, 1.0);
uniform vec4 tint_right : source_color = vec4(0.16, 0.51, 0.57, 1.0);
// 깊을수록 물이 두꺼워 바닥이 흐려진다.
uniform float murk_left : hint_range(0.0, 1.0) = 0.20;
uniform float murk_right : hint_range(0.0, 1.0) = 0.30;
// 물결 무늬가 구역 경계에서 끊기지 않도록 스트립 전체에서의 위치를 넘겨받는다.
uniform float x_offset = 0.0;
uniform vec2 rect_size = vec2(300.0, 220.0);
uniform float caustic_strength : hint_range(0.0, 0.4) = 0.13;
// 수면에서 내려오는 빛의 양. 밤에는 0에 가까워져 물결도 빛줄기도 잦아든다.
uniform float sun : hint_range(0.0, 1.0) = 1.0;
// 수면에서 내려오는 빛줄기. 얕은 구역에서만 뚜렷하고 깊어질수록 사라진다.
uniform float ray_left : hint_range(0.0, 1.0) = 0.7;
uniform float ray_right : hint_range(0.0, 1.0) = 0.6;
void fragment() {
vec2 px = vec2(x_offset, 0.0) + UV * rect_size;
vec3 tint = mix(tint_left.rgb, tint_right.rgb, UV.x);
float murk = mix(murk_left, murk_right, UV.x);
// 수면에서 갈라진 빛이 바닥에 드리우는 그물 무늬.
vec2 p = px / 78.0;
float c = sin(p.x + TIME * 0.45) * sin(p.y * 1.3 - TIME * 0.31);
c += sin(p.x * 1.7 - TIME * 0.38) * sin(p.y * 0.8 + TIME * 0.44);
float caustic = pow(max(c * 0.5 + 0.5, 0.0), 3.0) * sun;
// 밝은 물결 자리는 물이 얇아 보이도록 살짝 걷어낸다.
float alpha = clamp(murk - caustic * caustic_strength * 0.5, 0.0, 1.0);
vec3 col = tint + caustic * caustic_strength;
// 비스듬히 내려오는 빛줄기. 3/4 시점이라 화면 위쪽(먼 곳)에서 가장 밝고
// 앞으로 올수록 흩어진다. 물속임을 알려주는 가장 강한 신호다.
float rs = mix(ray_left, ray_right, UV.x) * sun;
if (rs > 0.001) {
// 거의 세로로 서되 살짝 기운다. y 계수를 크게 잡으면 화면이 높을 때
// 무늬가 가로로 누워버려 빛줄기로 안 보인다.
float g = px.x * 0.010 + px.y * 0.0035;
float r = (sin(g + TIME * 0.09) * 0.5 + 0.5)
* (sin(g * 2.3 - TIME * 0.06) * 0.5 + 0.5);
float rays = pow(r, 2.6) * rs * smoothstep(1.0, 0.02, UV.y);
// 빛줄기는 물을 걷어내는 게 아니라 물 속에 떠 있는 밝은 기둥이다.
// 알파를 낮추면 바닥만 밝아지고 물기둥은 텅 빈 채로 남는다.
col += rays * 0.38;
alpha = clamp(alpha + rays * 0.20, 0.0, 1.0);
}
COLOR = vec4(col, alpha);
}