어떻게 동작하나 How it works
1 · 곡면 The surface
z(x, t) = A · sin( 2π·x / λ − t·speed·2π )
종이 띠는 x(길이) × y(폭) 격자이고 높이는 x만의 함수입니다. Folded를 켜면 구간 경계에서만 z를 샘플하고 그 사이는 직선으로 이어서, 각 구간이 평평한 면(facet)이 됩니다.
The strip is a grid in x (length) × y (width); height depends on x only. “Folded” samples z only at segment boundaries and interpolates linearly, so each segment is one flat facet.
2 · 회전 Rotation (yaw + tilt)
⎡ cosθ −sinθ 0 ⎤
Rz(θ)=⎢ sinθ cosθ 0 ⎥ (rotate, 0–360°)
⎣ 0 0 1 ⎦
⎡ 1 0 0 ⎤
Rx(φ)=⎢ 0 cosφ sinφ ⎥ (tilt, 0° = side, 90° = top)
⎣ 0 −sinφ cosφ ⎦
행렬 라이브러리 없이 계수 8개(a…h)를 프레임당 한 번만 계산하고, 모든 점에 곱셈·덧셈만 적용합니다.
No matrix library: eight coefficients are computed once per frame, then every point costs a handful of multiply-adds.
3 · 투영 Projection
right = x′ = x cosθ − y sinθ up = z cosφ + y′ sinφ depth = y′ cosφ − z sinφ k = d / (d + depth) (d→∞ : 직교) sx = right · k · scale sy = −up · k · scale (SVG의 y는 아래쪽)
투영 해부를 켜면 5개 점의 3D 좌표 → 화면 좌표, 바닥 그림자 발자국, sx·sy 두 변을 직접 볼 수 있습니다.
Toggle “projection anatomy” to see five points: world coords → screen coords, floor footprint, and the sx / sy legs.
4 · 화가 알고리즘 Painter's sort
SVG에는 z-buffer가 없고 DOM 순서가 곧 그리기 순서입니다. 그래서 매 프레임 각 셀의 평균 카메라 깊이를 구해 먼 것 → 가까운 것 순으로 정렬하고, 그 순서대로 <path>에 d·fill을 씁니다. 회전할 때마다 순서가 바뀌므로 정렬은 매 프레임 필요합니다. 그림자는 같은 사각형을 바닥(z=0)에 비스듬히 투영해 한 개의 path로 합치고 SVG 블러 필터를 적용합니다.
SVG has no z-buffer — DOM order is paint order. Each frame we sort cells by mean camera depth, far → near, and write them into a pool of <path>s. The shadow is the same quads projected obliquely onto the floor, merged into one path, blurred by an SVG filter.
5 · 언제 WebGL로 넘어가나 When to switch to WebGL
병목은 수학이 아니라 DOM입니다. 요소 수가 늘면 속성 갱신, 스타일 계산, 래스터화가 선형 이상으로 느려집니다. 이 기기에서 Stress test를 돌린 결과:
아직 측정 전 — 패널의 Stress test 를 실행하세요. not measured yet — run “Stress test” in the panel.
- 수천 셀 이하, 정적 표현, 벡터 export가 필요 → SVG 유지 (접근성·.svg 저장·CSS 스타일링 장점).
- 수만 셀 이상, 60fps 필수, 텍스처·실시간 조명·z-buffer가 필요 → WebGL / WebGPU (정점은 GPU, 정렬은 depth test가 처리).
- 중간 지대 → Canvas 2D로 같은 painter's 루프를 돌리면 DOM 비용만 제거됩니다.
The bottleneck is the DOM, not the math. Stay on SVG for ≤ a few thousand cells and when vector export or CSS styling matter; move to WebGL/WebGPU for tens of thousands of cells, locked 60 fps, or real lighting. Canvas 2D is the middle step — same painter's loop, no DOM cost.