한국 미학

창호 문살 빛

하루의 해가 띠살 창호를 지나며 문살 그림자로 빈 방을 쓸고 간다.

창호 문살 빛 실행 화면
새 탭에서 보기

실제 코드로 재생되는 미리보기입니다

프롬프트 설정

Claude 가 읽는 제작 지시문입니다. 직접 읽지 않아도 됩니다.

한지 바른 창호로 들어온 햇빛이 하루 동안 빈 방을 쓸고 지나가는 18초 반복 애니메이션을 HTML 파일 하나로 만들어 줘. 미리보기에서 바로 돌아가게. 길게 설명할 테니 숫자는 그대로 지켜 줘. 사진처럼 믿기는 빛이 목표다 — 「그림 같은 방」이 아니라 「해가 실제로 움직이는 방」이어야 한다.

핵심 아이디어: 카메라는 고정이고, 움직이는 것은 빛뿐이다. 방은 작은 상자 하나다. 정면 벽 한 칸을 바닥까지 내려오는 세 짝 띠살 분합문이 다 채우고, 카메라는 그 앞에 앉은 눈높이에서 수평으로 보되 렌즈를 아래로 밀어(건축 사진의 시프트) 바닥을 화면 아래 절반에 넓게 둔다. 기둥과 문살은 화면에서 정확히 수직이다. 해가 떠 있는 동안 대부분 문살 무늬가 화면의 31~45% 를 덮는다 — 주인공은 빛 무늬다.
각 픽셀에서 해 쪽으로 광선을 거슬러 올라가 창 평면에 닿은 자리의 문살 투과율을 읽는다(평행 광원). 그래서 문살 그림자는 벽과 바닥에 걸쳐도 모서리에서 정확히 이어지고, 창에서 먼 곳일수록 한지를 지난 빛이 넓게 퍼져 가장자리가 무르다. 해는 실제 태양 경로 공식으로 움직여 아침에는 오른쪽 벽을 덮었다가 바닥으로 흘러내리고 → 한낮에는 문 앞 바닥을 폭 전체로 덮고 → 저녁에는 왼쪽 벽을 타고 오른다. 빛 색은 해 뜸 살구빛 → 한낮 흰빛 → 노을 주황 → 보라 잔광 → 남색 밤 → 푸른 새벽으로 흐른다. 해가 없을 때는 기름 먹인 장판에 비친 창이 두 번째 주인공이다.
한낮에는 바람이 문을 스치며 창호지가 숨 쉬듯 부푼다. 바닥 무늬는 흐려지지 않은 채 살 선이 물결처럼 휘고, 칸 하나하나가 베개처럼 부풀며 밝아졌다 가라앉는 결이 왼쪽에서 오른쪽으로 지나간다.
첫 화면은 해 뜬 직후다 — 재생 0초에 이미 오른쪽 벽에 살구빛 문살 무늬가 켜져 있다.

[바꿀 곳]
- 색: 도배 한지 벽 #E9E0CF · 장판 #C6923F · 나무(문틀·살·기둥·인방) #5B4030 · 창호지 투과색 #FFF4E2
- 길이: 18초 (끝나면 처음으로 이어서 반복)
- 시작 시각(장면 시각 s 로): 2.1 — 재생 시각 t 에서 s = (t + 2.1) mod 18
- 해 뜸 s 1.5 · 해 짐 s 13.5 · 바람 숨 시작 s 7.0 (재생 4.9초)
- 위도 37.6° · 태양 적위 −23.4° (동지 무렵 — 해가 가장 낮아 무늬가 가장 깊이 들어온다. −10° 면 늦가을, 0° 면 봄가을이고 무늬가 짧아진다)
- 화면비: 16:9 (기준 1920×1080)

[크기] — 공간·창·카메라. 길이 단위는 미터. x = 창에서 방 안쪽(북), y = 위, z = 동쪽
- 방은 상자 x∈[0, 5.0], y∈[0, 2.4], z∈[0, 2.9]. 문 벽은 x=0 면(남쪽 벽, 바깥이 해 쪽).
- 카메라: 눈 (2.4, 0.65, 1.50) · 바라보는 점 (0.3, 0.65, 1.42)(수평) · 세로 화각 84° · 렌즈 시프트 −0.25 · 고정.
  f = normalize(바라보는 점 − 눈), right = normalize(cross(f, (0,1,0))), up = cross(right, f),
  광선 = normalize(f + ndc.x·tan42°·(16/9)·right + (ndc.y·tan42° − 0.25)·up). right 가 −z 쪽이라 z=0 벽(서쪽)이 화면 오른쪽, z=2.9 벽(동쪽)이 왼쪽이다.
- 분합문 바깥틀(이하 「창」): z∈[0.12, 2.78](양쪽 기둥 사이 한 칸 전체), y∈[0.08, 2.02](문지방 위 ~ 상인방 아래). 문틀 폭 0.06. 그 안에 문짝 세 짝(각 폭 0.847), 문짝 울거미 폭 0.045.
  문짝 하나의 살 들어가는 칸 = 폭 0.757 × 높이 1.73.
- 띠살(실제 띠살문 비례): 세로살 11개, 살 굵기 0.013, 살 중심 간격 p = 0.757/12 = 0.0631(살 사이 빈칸 0.0501).
  가로살은 세 띠에만 있다 — 칸 위에서부터 칸 높이의 12% · 50% · 88% 자리를 중심으로 띠마다 가로살 4개, 간격 같은 p. 띠 안은 정사각 칸, 띠 사이는 긴 세로 칸이다.
- 나무: 모든 벽의 걸레받이(하인방) y<0.10, 상인방 y∈[2.02, 2.14], 문 벽 양 끝 기둥(z<0.12, z>2.78), 옆벽의 문 쪽 끝(x<0.12), 문지방 y<0.08.
- 화면에서 이렇게 보이면 맞다(1920×1080):
  - 창 바깥틀: 가로 0.32W~0.66W, 세로 0.04H~0.49H.
  - 상인방은 0.016H~0.044H 에 가로 띠로 걸리고, 그 위로 벽이 한 줄 보인다.
  - 문 벽과 바닥이 만나는 선은 0.51H 이고, 그 아래가 전부 장판이다. 옆벽 둘이 화면 양쪽 약 0.32W 씩이다.
  - 기둥·문살·벽 모서리는 화면에서 기울지 않은 수직선이다. 문살 하나가 약 3px 이다.
- 빛 무늬가 화면을 덮는 비율(장면 시각 s · 검산값 ±3%p · 「직사광을 끈 판보다 8/255 넘게 밝은 픽셀」):
  1.75 18% · 2.1 23% · 2.5 31% · 3.0 35% · 4.0 42% · 5.25 45% · 6.0 41% · 6.5~8.75 35% · 9.5 44% · 10.0 44% · 11.0 42% · 11.5 40% · 12.0 34% · 12.5 31% · 13.0 22% · 13.25 17%
- 빛 무늬 자리(검산값):
  - s 2.1: 오른쪽 벽, 가로 0.54W~1.0W.
  - s 3.0: 오른쪽 벽 전체 높이 + 바닥 오른쪽, 가로 0.36W~1.0W.
  - s 5.25: 오른쪽 벽 + 바닥, 가로 0.11W~1.0W.
  - s 6.5~8.75: 문 앞 바닥, 화면 폭 전체 · 0.53H~아래 끝.
  - s 10.0: 왼쪽 벽 + 바닥, 가로 0~0.87W.
  - s 11.5: 왼쪽 벽 전체 높이 + 바닥 왼쪽, 가로 0~0.64W.
  - s 12.5: 왼쪽 벽 + 문 앞 바닥 왼쪽, 가로 0~0.60W.
  - s 13.25: 왼쪽 벽 0~0.29W 만.

[빛 — 문살 투과율 T(u, v, r)]
창 평면 좌표 u = z, v = y. r = 흐림 반지름(미터). 폭 2r 상자 커널로 흐린 값을 닫힌 식으로 구한다(반복 합·텍스처 블러 없음).
- 주기 막대의 원시함수: F(x; c0, p, w) = w·floor(y/p) + clamp(mod(y, p), 0, w), y = x − c0 + w/2 (막대 중심 c0 + k·p, 폭 w).
- 세로살: Tu = 1 − clamp((F(u+r) − F(u−r)) / (2r), 0, 1), c0 = 그 문짝 칸의 z 가 작은 쪽 끝 + p.
- 가로살 띠 하나(b0 = 띠 중심 − 2p, b1 = 띠 중심 + 2p): G(x) = F(clamp(x, b0, b1); b0 + p/2, p, w) − F(b0; b0 + p/2, p, w). 덮임 = (G(v+r) − G(v−r)) / (2r). Tv = clamp(1 − 세 띠 덮임의 합, 0, 1).
- 칸 마스크: boxstep(x; e0, e1, r) = clamp((min(x+r, e1) − max(x−r, e0)) / (2r), 0, 1) 을 u·v 각각 곱한다.
- 떨어진 빛용 T = Σ(세 문짝) 마스크·(0.15 + 0.85·Tu·Tv). 0.15 는 종이가 흩은 빛이 살 그림자 안까지 조금 채우는 몫이다(바닥·벽의 살 그림자가 완전히 검어지지 않는다). 바닥·벽에 떨어지는 직사와 장판 반사에만 쓴다. 울거미·문틀은 마스크 밖이라 그대로 0 이다.
- 직접 보이는 창용 T_view = Σ(세 문짝) 마스크·Tu·Tv(0.15 없음). 방 안에서 보는 살은 종이 앞에 선 단단한 나무라, 흩은 빛이 살 앞을 채우지 않는다.
- 상자 커널은 가로·세로로 나뉘므로 Tu·Tv 곱이 정확한 흐림이다.

[해와 빛 색] — 모든 시각은 장면 시각 s
- 해 경로(1.5 < s < 13.5 일 때만):
  - q = (s − 1.5)/12, k = 2q − 1, H0 = acos(−tan φ · tan δ) = 70.5°, 시간각 h = H0·(0.5·k + 0.5·k³). k³ 항 때문에 해 뜸·해 짐 근처는 빨리 지나가고 한낮에 오래 머문다.
  - N = sin δ·cos φ − cos δ·sin φ·cos h · U = sin δ·sin φ + cos δ·cos φ·cos h · E = −cos δ·sin h. 해 쪽 방향 S = (N, U, E), 빛 진행 방향 L = −S.
  - 검산: s 2.4 → S ≈ (−0.66, 0.21, 0.72), 고도 12.1° · s 4.0 → (−0.81, 0.40, 0.42), 23.7° · s 7.5 → (−0.87, 0.48, 0.00), 29.0° · s 13.0 → (−0.60, 0.13, −0.79), 7.3°.
- 열쇠값은 hex 를 선형으로 바꾼 뒤(채널^2.2) 선형 RGB 에서 직선 보간한다. 18.0 값 = 0.0 값.
  - 하늘빛(창호지 뒤의 하늘) [s, 색, 세기]: 0.0 #3D5A9E 0.55 · 1.5 #8FA8D8 0.80 · 3.7 #DCE4F0 1.00 · 7.5 #F2F1EC 1.15 · 11.3 #F3E2C8 1.00 · 13.5 #E89A6A 0.72 · 14.4 #9A6A9C 0.50 · 15.3 #34407A 0.54 · 16.6 #2A3468 0.52 · 18.0 #3D5A9E 0.55
  - 햇빛 [s, 색(약 색온도), 세기]: 1.5 #FF7A3A 0 (1900K) · 2.4 #FFA463 3.5 (2600K) · 3.9 #FFD2A1 7.0 (3600K) · 5.9 #FFF0DE 8.7 (5000K) · 7.5 #FFF8F0 9.3 (5600K) · 9.8 #FFEBD2 8.7 (4600K) · 11.8 #FFB772 7.0 (3000K) · 12.8 #FF8838 4.1 (2200K) · 13.5 #FF5E24 0. 범위 밖은 0.
  - 같은 고도라도 저녁이 아침보다 붉다(2.4 와 12.8 을 비교).
- cosInc = max(0, −S.x)(창에 들어오는 각), 한지 직진 투과 τ = 0.6·(0.4 + 0.6·cosInc).
- 창호지 평균 밝기 Lw = 하늘색·하늘세기·0.6 + 햇빛색·햇빛세기·0.16·cosInc·(0.4 + 0.6·cosInc).
- 노출(카메라 자동 노출 — 밤에 방이 꺼지지 않게): 노출 = 1 + 3.2·(1 − smoothstep(0.30, 0.90, 하늘세기)). 낮은 1.0, 가장 어두운 s 16.6 에서 약 3.2.

[면마다 그리는 법] — 모든 픽셀은 상자 안쪽 여섯 면 중 하나에 닿는다(각 축에서 나가는 면까지의 거리 중 최솟값). 면 법선 n 은 방 안쪽, d 는 시선 방향, 픽셀 하나 길이 pix = 눈에서의 거리 × 2·tan42° / 그리기 버퍼 높이(픽셀).
- 직사광(창 벽 x=0 면 제외, S.y > 0 일 때):
  - 창 평면의 점: tw = P.x / L.x, u = P.z − L.z·tw, v = P.y − L.y·tw.
  - 흐림 r = max(0.002 + 0.009·tw, 0.7·pix / max(|n·d|, 0.12)) × (1 + 0.3·a). 3m 떨어진 곳에서 0.029 로 빈칸 0.050 보다 작아 살이 뭉개지지 않는다. 뒤의 바닥값은 작은 화면에서 문살 무늬가 지글거리지 않고 고르게 녹게 한다. a 는 바람 숨 세기(아래, 평소 0).
  - 직사 = 햇빛색·햇빛세기·τ·T(u′, v′, r)·max(0, n·S)·(1.15 − 0.50·섬유(u, v, 흐리게))·숨 결. u′·v′·숨 결은 [장면] 4 의 바람 숨 식이고, 평소에는 u′=u, v′=v, 숨 결 1 이다.
  - 방은 볼록한 상자라 가리는 것을 따로 검사하지 않는다. 벽 위와 바닥 위를 같은 식으로 계산하므로 꺾임선에서 무늬가 저절로 이어진다.
- 창 빛(부드러운 면광원): ŵ = normalize(창 중심 (0, 1.05, 1.45) − P), dist² = |창 중심 − P|².
  창빛 = 1.4 · 2.8 · max(0, n·ŵ) · max(0, −ŵ.x) / (π·(dist² + 0.5)) · Lw.
- 채움빛 = 0.05·Lw·2.8 + 반사빛. 반사빛 = 0.05·햇빛세기·τ·max(S.y, 0)·햇빛색·(장판 선형색 / 그 최댓값) — 해가 바닥을 비추면 방 전체가 따뜻해진다.
- 모서리 어둠(바닥·옆벽·천장만): 창빛과 채움빛에 0.6 + 0.4·smoothstep(0, 0.45, m) 를 곱한다. m = 그 점에서 자기 면의 네 모서리까지 거리 중 최솟값.
- 문 벽(x=0 면)은 창 안팎을 가리지 않고 한 가지 식이다. 빛 = 채움빛 + 0.1·Lw 이고, 모서리 어둠은 없다. 도배지든 기둥·문지방·문틀·울거미·살이든 바탕색만 다르다. 문틀 둘레에 직사각 이음선이 생기지 않는다.
- 색 = 바탕색(선형) × (직사 + 창빛 + 채움빛). 바탕색은 벽·천장이 도배 한지(천장은 ×0.9), 나무가 나무, 바닥이 장판(아래)이다.
- 장판(콩기름 먹인 종이 바닥):
  - 장판지 한 장 = 0.90(x) × 0.60(z), 홀수 줄은 x 로 0.45 엇갈린다.
  - 이음새는 어두운 줄눈이 아니라 겹침이다. 각 장의 x·z 가 작은 쪽 1.5cm 띠는 ×1.04(두 겹이라 기름이 더 먹음)이고, 그 띠 끝에 2mm 선만 ×0.90.
  - 벽에서 0.3m 안은 ×0.94(덜 밟혀 기름이 덜 먹은 가장자리).
  - 장마다 시드 해시로 ×0.96~1.04, 큰 얼룩 값 노이즈(크기 0.35m, 2옥타브) ×0.94~1.06.
  - 광택(창이 바닥에 금빛으로 비친다):
    - 시선 d 를 바닥에서 뒤집은 R(y 부호만 반대)로 창 벽까지 tr = −P.x / R.x(R.x < 0 일 때), 닿은 점은 (ur, vr).
    - 반사 = 3.8 × 1.7 × F × T(ur, vr, rr) × 창호지 밝기 × (0.45 + 0.55·얼룩) × exp(−0.30·tr) × (1 − 0.6·smoothstep(0.1, 0.75, 햇빛세기/9)).
    - F = 0.06 + 0.30·(1 − (−d.y))^5, rr = max(0.004 + 0.12·tr, 0.7·pix / max(|d.y|, 0.12)). 얼룩은 위 장판 얼룩 값 노이즈(0~1)다.
    - 기름 먹인 종이의 광택은 문 가까이에서만 또렷하고, 멀어질수록 무르고 옅은 금빛 번짐이 되며, 기름이 고르게 먹지 않아 얼룩진다. 해가 바닥을 비추는 동안에는 반사가 줄어 문살 그림자를 바래지 않는다.
    - 검산: 새벽·잔광·밤(s 0.0 · 14.0 · 16.6)에 문 앞 장판(0.52H~0.60H)에 비친 창의 가장 밝은 곳이 창호지 밝기(톤 매핑 뒤)의 32~35% 이고, 화면 아래 끝(0.92H~)에서는 그 문 앞 값의 약 26% 로 줄어든다. 정오 바닥의 울거미 그림자는 밝은 칸의 약 65%(반사를 끈 판 57%)다.
- 창 벽(x=0)에서 바깥틀 안은 직접 보이는 창이다.
  - rView = 0.8·pix 로 T_view(z, y, rView) 를 구한다.
  - 색 = 창호지 밝기 × T_view × 숨 결 + 나무 × (채움빛 + 0.1·Lw) × (1 − T_view). 검산: 정오(s 7.5) 1080p 에서 세로살의 가장 어두운 픽셀이 약 48/255 로 울거미 나무와 같은 계열이다.
  - 창호지 밝기 = Lw × 투과색(선형, 최댓값 1로 정규화) × (1.15 − 0.50·섬유(z, y)).
- 한지 섬유 텍스처:
  - 시작할 때 Canvas2D 로 1024×1024 를 한 번 그려 반복(REPEAT) + 밉맵 텍스처로 올린다.
  - 검정 위에 흰 얼룩 160개(방사 그라디언트, 반지름 30~110px, 불투명도 10~25%) + 섬유 2,600개(2차 베지어, 길이 20~90px, 굵기 0.6~1.6px, 불투명도 15~35%, 방향 완전 무작위)를 그린다. 가장자리에 걸린 것은 ±1024 위치에도 그려 이음매 없이 잇는다.
  - 섬유 = 빨강 채널 0~1. 창에서는 텍스처 한 장 = 0.40m(섬유 0.8~3.5cm). 직사광에서는 같은 자리를 밉 편향 +4 로 흐리게 읽는다.
  - 벽 도배지는 한 장 = 0.60m, 바탕색 ×(0.96 + 0.08·(1 − 섬유)) 로 아주 옅게.
- 마무리:
  1. 결과 = 1 − exp(−노출 × 색)
  2. 감마 1/2.2
  3. 비네팅 ×(1 − 0.12·ρ²)(ρ = 화면 중심에서 모서리까지를 1)
  4. 고정 디더 ±0.5/255(픽셀 좌표 해시, 시간에 따라 바뀌지 않음)

[장면] (18초 반복. 화면은 재생 시각 t 가 아니라 장면 시각 s = (t + 2.1) mod 18 로 그린다. 아래 시각은 전부 s 이고, 괄호 안이 재생 시각 t)
1. s 2.1~5.5 (t 0.0~3.4) 해 뜸:
   - 재생 0초 화면에 이미 오른쪽 벽 위아래로 살구빛 문살 무늬가 켜져 있다(덮는 비율 23%). 0.9초 뒤(s 3.0) 35%, s 5.25 에 45% 까지 번진다.
   - 해가 오르며 무늬가 벽을 따라 흘러내려 바닥 오른쪽으로 번지고, 벽-바닥 꺾임에서 이어진다.
2. s 6.5~8.75 (t 4.4~6.65) 한낮: 무늬가 바닥으로 다 내려와 문 앞 장판을 폭 전체로 덮는다. s 7.5 정오에 흰빛, 문 가까운 쪽 띠살은 또렷하고 먼 쪽은 무르다.
3. s 7.0~9.3 (t 4.9~7.2) 시그니처 — 바람의 숨. 무늬가 화면 아래 절반을 꽉 채운 자리에서 일어난다.
   - 바람은 문을 화면 왼쪽(z=2.78)에서 오른쪽(z=0.12)으로 3.0m/초로 0.89초에 스친다.
   - 세기 a(s, u) = env(s − 7.0 − (2.78 − u)/3.0). env(τ) = sin²(π·τ/0.7)(0 ≤ τ < 0.7) · 0.45·sin²(π·τ/0.7)(0.7 ≤ τ < 1.4) · 그 밖 0. 두 번 숨 쉬고(두 번째는 약하게) 멎는다.
   - 흔들림: 창 평면 읽는 자리를 u′ = u + 0.012·a·sin(2π(v/0.45 + 0.6s)), v′ = v + 0.012·a·sin(2π(u/0.40 − 0.5s)) 로 옮긴다. 최대 12mm 로 빈칸 절반 25mm 보다 작아 살이 엉키지 않고, 파장이 길어 살 선이 물결로 휜다.
   - 흐림은 거의 그대로다(r ×(1 + 0.3a)). 무늬는 흐려지지 않는다.
   - 숨 결: cu = clamp(mod(u′ − c0 − w/2, p) / (p − w), 0, 1)(살 가장자리에서 0·1, 빈칸 가운데 0.5) 로 숨 결 = 1 + 0.30·a·(sin(π·cu) − 0.637). 바닥·벽에 떨어진 직사와 직접 보이는 창호지에 둘 다 곱한다. 0.637 = 2/π 라 평균 밝기는 그대로이고, 빛 무늬의 칸마다 베개처럼 부푼 결이 생긴다.
   - 검산(960×540, s 7.6 근처): 바닥 무늬 세부(4px 가우시안 고역 평균)는 바람 없는 판의 105%, 프레임 사이 변화는 +23%. 흐려짐이 아니라 움직임이다.
4. s 8.75~13.5 (t 6.65~11.4) 오후→노을: 무늬가 왼쪽으로 기울며 왼쪽 벽을 타고 올라 벽 전체 높이를 덮고, 색이 주황으로 짙어진다. s 12.5 에도 31% 를 덮고, s 13.0~13.5 에 왼쪽 벽 가장자리에서 붉게 가늘어지다 꺼진다.
5. s 13.5~15.3 (t 11.4~13.2) 잔광: 직사광 없음. 창호지가 주황 → 보라로 식고, 장판에 비친 창이 화면의 두 번째 주인공이 된다.
6. s 15.3~18.0 (t 13.2~15.9) 밤: 남색 방. 노출이 올라가 가장 어두운 s 16.6(t 14.5)에도 화면 평균 밝기가 약 25/255 이고, 문살 실루엣과 장판의 창 반사가 읽힌다.
7. s 0.0~2.1 (t 15.9~18.0) 새벽: 푸르게 밝아지고 s 1.5 에 해가 떠, t 18.0 = t 0.0 화면으로 이어진다.

[구현]
- HTML 파일 하나로 만든다. 외부 파일·글꼴·라이브러리·네트워크 요청을 쓰지 않는다(미리보기에서 막히거나 느려진다).
- 첫 <script> 맨 앞에 CONFIG 객체를 두고 [바꿀 곳]의 값과 이 글에 나온 숫자(시간표·크기·색·세기)를 이름 붙여 모은다. 나중에 숫자만 바꿔 다듬을 수 있게.
- 그림은 시간 t(초)만으로 계산하는 함수 render(t) 로 그린다. requestAnimationFrame 의 타임스탬프나 performance.now() 로 t 를 구한다. setTimeout·setInterval·CSS 애니메이션·transition 으로 움직이지 않는다(프레임마다 속도가 달라지고, 다시 재생할 때 어긋난다). 시뮬레이션처럼 상태가 쌓이는 작품은 고정 시간 간격으로 상태를 진행하되 그 진행도 타임스탬프로만 정한다.
- 난수는 시드 고정 난수(mulberry32 등)만 쓴다. Math.random 은 쓰지 않는다(매번 다른 화면이 나온다).
- 캔버스 내부 해상도는 화면비에 맞춘 기준 크기로 고정하고, 창 크기에 맞춰 화면비를 지키며 가운데에 꽉 차게 보이게 한다(남는 곳은 배경색). 스크롤이 생기지 않게 한다. devicePixelRatio 는 그리는 선명도에만 반영한다.
- 글자는 시스템 글꼴만 쓴다: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif. 붓글씨·손글씨 느낌은 글꼴이 아니라 획을 그려서 낸다.
- 길이가 정해진 작품은 끝나면 처음과 같은 화면으로 돌아가 이음매 없이 반복한다.
- 모든 함수·상수·셰이더 문자열을 먼저 정의하고, 시작(초기화와 첫 requestAnimationFrame)은 스크립트 맨 끝에서 한 번만 호출한다. 정의되기 전에 쓰면 첫 화면에서 멈춘다.

이 작품에만 해당하는 구현:
- 그리기 방식:
  - WebGL1 전체 화면 사각형 하나 + 프래그먼트 셰이더 하나(precision highp float)로 방 전체를 그린다. 픽셀마다 광선을 쏴 상자 면을 찾고 위 식을 그대로 계산한다.
  - WebGL 이 없으면 화면 가운데에 「이 기기에서는 WebGL이 필요합니다」 한 줄만 띄운다.
- render(t) 는 맨 먼저 s = (t + CONFIG.timing.startOffset) mod 18 을 구한다.
  - 시간에 따라 바뀌는 값(S·L·cosInc·τ·햇빛색·햇빛세기·하늘색·하늘세기·Lw·노출·s)은 JS 가 계산해 uniform 으로 넘긴다. 셰이더 안에서 시각표를 다시 계산하지 않는다.
  - 바람 세기 a 는 u 에 따라 달라지므로 셰이더가 s 로 계산한다.
- 그리기 버퍼 = 화면 표시 크기 × min(devicePixelRatio, 2), 단 2560×1440 을 넘지 않게. 버퍼 높이를 uniform 으로 넘겨 pix 를 구한다. 레터박스 바깥은 #0B0C10.
- 섬유 텍스처는 2의 거듭제곱(1024)이어야 WebGL1 에서 REPEAT·밉맵이 된다. LINEAR_MIPMAP_LINEAR.
- CONFIG 묶음:
  - CONFIG.timing = { period 18, startOffset 2.1, sunrise 1.5, sunset 13.5, breathStart 7.0, breathSpeed 3.0, breathLen 1.4 }
  - CONFIG.skyKeys·sunKeys 는 위 표 그대로.
  - CONFIG.lattice·room·camera(shift −0.25 포함)·window·floor·sheen·exposure 에 위 숫자.
- 화면에 글자·버튼은 없다. 스페이스바로 일시정지/재생(멈춘 시각에서 이어 간다)만 둔다.
- 시작할 때 자체 대조(합격 기준):
  - 셰이더에 uMode uniform 을 둔다. 0 = 보통 그림. 1 = 같은 픽셀을 직사광 포함·제외 두 번 계산해 톤 매핑 뒤 채널 평균 차이가 8/255 를 넘으면 흰색, 아니면 검정.
  - 첫 프레임 전에 480×270 프레임버퍼(RGBA8 텍스처)에 아래 장면 시각을 그려 readPixels 로 잰다. 이때 pix 도 버퍼 높이 270 으로 계산한다.
  - 결과를 console.table 로 [항목, 기대, 실제, PASS/FAIL] 출력한다. FAIL 이 있어도 재생은 계속한다.
  - 대조 항목:
    - s(t=0) = 2.1, s(t=18) = s(t=0)
    - 해 방향 S: s 2.4 (−0.66, 0.21, 0.72) · s 7.5 (−0.87, 0.48, 0.00) · s 13.0 (−0.60, 0.13, −0.79), 성분마다 ±0.02
    - H0 70.5° ±0.1 · 살 간격 p 0.0631 · 빈칸 0.0501 · 바람 흔들림 최대 0.012 < 빈칸/2
    - 덮는 비율(uMode 1, 흰 픽셀 비율): s 2.1 23% · s 3.0 35% · s 7.5 36% · s 10.0 45% · s 12.5 31%, 각 ±5%p
    - 밝기(uMode 0, 화면 평균 RGB): s 16.6 ≥ 22/255 · s 2.1 ≥ 60/255
    - 직접 보이는 살(uMode 0, s 7.5, 바람 세기 0): 1920×1080 화면의 일부만 그리도록 셰이더에 uOffset·uFull uniform 을 둔다(ndc 는 (gl_FragCoord.xy + uOffset) / uFull 로, pix 는 uFull.y 로 구한다. 평소에는 uOffset 0, uFull = 버퍼 크기). 화면 위에서부터 y 176~240, 왼쪽에서 x 874~1024 칸(가운데 문짝 띠 사이 세로 칸)을 150×64 프레임버퍼에 그린다(gl_FragCoord 는 아래가 0 이므로 uOffset.y = 1080 − 240). 가장 어두운 픽셀의 RGB 평균 ≤ 70/255 (검산 48).
    - 반사 속 그림자 깊이(uMode 0, 480×270, s 7.5, 바람 세기 0): 화면 위에서부터 (x, y) 픽셀 3×3 평균으로 울거미 그림자 A1 (292, 177) · A2 (311, 203), 밝은 칸 B1 (236, 178) · B2 (237, 205). (A1 + A2)/(B1 + B2) ≤ 0.70 (검산 0.65 · 고르게 거울처럼 비친 판은 0.75 로 FAIL).

[하지 말 것]
- 재생 0초를 장면 시각 0(새벽 어둠)에서 시작하지 않는다 — 첫 1초가 검은 방이면 엄지가 멈추지 않고, 처음부터 녹화한 파일도 검은 화면으로 시작한다. 0초는 해 뜬 직후 무늬가 켜진 화면이다.
- 바람 숨을 흐림으로 만들지 않는다 — 흐림을 크게 키우면 「일렁임」이 아니라 「초점이 나갔다 돌아옴」으로 읽히고, 주인공인 무늬가 잠깐 지워진다. 살 선이 휘고 칸이 부푸는 움직임이어야 한다.
- 카메라를 내려다보게 기울이지 않는다 — 수직선이 기울어 「광각 CG 방」이 된다. 수평 카메라 + 렌즈 시프트가 한옥 실내 사진의 정석이다.
- 카메라 자리·화각 84°·시프트·문 크기를 줄이거나 바꾸지 않는다 — 빛 무늬가 해 있는 동안 화면의 31~45% 를 덮도록 계산한 값이다. 화각을 좁히거나 카메라를 뒤로 빼면 문이 화면 가운데의 작은 창이 되고 무늬가 화면 밖으로 나간다.
- 직사광 흐림에서 화면 픽셀 바닥값을 빼지 않는다 — 폰 크기에서 문 앞 장판에 점무늬 모아레가 생겨 지글거린다.
- 빛기둥(볼류메트릭 광선·god ray)이나 빛 속에 떠다니는 먼지를 넣지 않는다 — 한지가 빛을 흩어서 방 안 공기에 선명한 빛기둥이 서지 않고, 먼지 입자는 시선을 문살 그림자에서 빼앗는 가장 흔한 상투다.
- 블룸·글로우·렌즈 플레어를 넣지 않는다 — 창은 종이를 지난 확산광이라 번쩍이지 않고, 번짐이 3px 짜리 문살 실루엣을 지운다.
- 그림자 흐림을 ctx.filter·CSS blur·화면 공간 블러로 만들지 않는다 — 흐림이 창에서의 거리에 비례해야 「창 가까이는 또렷, 멀리는 무름」이 보인다.
- 문살 무늬를 그림 한 장으로 구워 벽과 바닥에 원근 변환해 붙이지 않는다 — 벽과 바닥이 만나는 꺾임선에서 무늬가 어긋난다. 픽셀마다 해 쪽으로 거슬러 창 평면을 읽어야 이어진다.
- 문살을 바둑판 격자로 바꾸지 않는다 — 띠살의 정체는 촘촘한 세로살과 세 띠의 가로살이다. 고른 격자는 다른 나라 미닫이나 일반 창살로 읽힌다.
- 해를 원이나 좌우 직선으로 돌리지 않는다 — 위 태양 경로 식이어야 아침 무늬가 오른쪽 벽에 눕고, 한낮에 바닥으로 내려오고, 저녁에 반대편 벽으로 넘어가는 비대칭이 생긴다.
- 장판 이음새를 어두운 줄눈 격자로 그리지 않는다 — 큰 바닥 타일로 읽힌다. 장판지는 겹쳐 붙이므로 이음새는 살짝 진한 띠와 가는 끝선이다.
- 장판에 나뭇결이나 마루 널 무늬를 넣지 않는다 — 장판은 기름 먹인 종이 바닥이다.
- 문 벽의 나무를 창 안쪽과 바깥쪽에서 다른 식으로 칠하지 않는다 — 문틀 둘레에 직사각 이음선이 보인다.
- 직접 보이는 창의 살에 흩은 빛 0.15 를 섞지 않는다 — 살이 나무가 아니라 종이에 인쇄된 회색 줄로 씻긴다.
- 장판 반사를 거리와 상관없이 고른 세기로 비추지 않는다 — 가장자리가 곧은 유리판·니스 마루가 되고, 정오에는 반사 기둥 안의 문살 그림자만 바래 흰 직사각 유령이 생긴다.
- 사람·가구·방석·화분·창밖 풍경·해·달·별을 그리지 않는다 — 빈 방과 빛만이 이 작품의 전부다. 창 너머가 보이면 한지가 아니라 유리가 된다.
- 시계·시각·날씨 같은 글자를 넣지 않는다 — 시간은 빛의 색과 그림자의 길이로만 읽혀야 한다.
- 카메라를 움직이지 않는다(줌·흔들림·패닝 금지) — 움직이는 것이 빛뿐이어야 그림자가 방을 쓸고 가는 것이 보인다.
- 매 프레임 바뀌는 필름 그레인·노이즈를 넣지 않는다 — 고요한 방이 지글거린다. 디더는 시간에 따라 바뀌지 않는 고정 패턴만.
- 한지 섬유를 셰이더 안의 늘인 노이즈로 만들지 않는다 — 몇 방향으로만 늘어선 직선 빗금 무늬가 되어 기계 질감이 난다. Canvas2D 로 그린 곡선 섬유 텍스처를 쓴다.
- 바람 숨에 창틀·문살을 흔들거나 휘게 하지 않는다 — 나무 살은 단단하고 종이와 빛만 숨 쉰다. 틀이 흔들리면 지진처럼 보인다.
- 밤을 완전한 검정으로 만들지 않는다 — 폰 밝은 화면에서 꺼진 화면으로 읽힌다. 노출 식이 밤을 남색으로 지킨다.
- 빛 색을 sRGB 값 그대로나 HSL 로 섞지 않는다 — 노을 주황에서 보라로 넘어갈 때 탁한 회색이 낀다. 선형 RGB 에서 섞는다.

사용 방법

필요한 것: claude.ai 계정 — 무료 계정에서도 Claude Opus 5.5 를 고를 수 있습니다

  1. claude.ai 에서 새 대화를 엽니다.
  2. 모델 메뉴에서 Claude Opus 5.5 를 고르고, 같은 메뉴의 Effort(답변 깊이)를 High 로 둡니다.
  3. 복사한 프롬프트를 붙여 넣고 전송합니다. 결과로 나온 HTML 파일을 브라우저로 열면 재생됩니다.
권장 모델
Claude Opus 5.5 · Effort High
화면비
16:9 (가로)
재생 길이
18초
결과물
HTML 파일 하나 · 따로 설치할 것 없음
영상 파일
위 「MP4 저장 기능 포함」을 켜면 결과 화면에 녹화 단추가 생깁니다 1080 기준 · 12 Mbps · 브라우저에 따라 MP4 또는 WebM

추가 요청 예시

결과가 나온 뒤 같은 대화에서 이어서 요청하면 해당 부분만 수정됩니다.

  • 해의 계절을 봄·가을로 바꿔 줘(태양 적위 0°). 한낮의 문살 무늬가 문 앞에 더 짧고 또렷하게 놓이게.
  • 해 질 녘 햇빛을 더 짙은 다홍으로 하고, 해가 진 뒤 남는 빛은 보라 대신 깊은 남색으로 금방 어두워지게 바꿔 줘.
  • 전체를 30초로 늘리고, 해 뜨고 지는 시각과 바람이 창호지를 스치는 시각도 같은 비율로 늦춰 더 느긋하게 해 줘.

한국 미학

같은 카테고리의 다른 프롬프트

한국 미학 전체 보기

모든 모션 보기 블로그 글 목록 RSS 로 새 글 받기