Captain's Log
← Observatory
Observatory·

그리드 필드 스터디 — @seohyo 작가님 오마주

@seohyo 작가님의 그리드 기반 제너러티브 애니메이션을 분석하고 바닐라 Canvas 2D로 재현한 스터디. 시간축을 가진 노이즈 필드를 밴드로 양자화하고, 각 밴드에 제한된 글리프 어휘와 4색 팔레트를 매핑하면 등고선을 따라 도넛 사슬이 나타난다.

TrainingCreative CodingGenerative ArtCanvas

배경

인상 깊은 제너러티브 아트 작품을 분석하고, 그 원리를 코드로 재현하는 연습을 시작했다. 이 랩 일지의 첫 대상은 서울을 기반으로 활동하시는 미디어 아티스트 @seohyo 작가님의 그리드 기반 애니메이션이다. 검정 바탕 위에 점·도넛·십자·줄무늬가 빽빽한 격자를 이루고, 유기적인 덩어리들이 스크롤 없이 제자리에서 천천히 숨 쉬듯 변한다. 처음 봤을 때는 복잡해 보였지만, 뜯어볼수록 감탄만 나왔다 — 작가님이 만들어 내시는 화면은 "적은 규칙에서 나오는 풍부함"의 교과서였다.

라이브러리 없이 바닐라 Canvas 2D 단일 HTML로 재현했다. 구조는 Processing/p5.js 스케치와 1:1로 대응하므로, 그대로 옮겨 심을 수 있다.

원리 분석

화면을 오래 관찰하며 세운 가설은 세 문장으로 요약된다.

  1. 정사각 그리드 — 캔버스를 짧은 변 기준 42셀의 정사각 격자로 나눈다.
  2. 시간축 노이즈 필드 — 3D 노이즈를 (x, y, t)로 샘플링한다. 시간축 t를 천천히 흘리면 필드가 이동하지 않고 제자리에서 진화한다.
  3. 밴드 양자화 → 글리프 매핑 — 연속적인 필드 값을 9개 구간(band)으로 자르고, 각 구간에 제한된 글리프 어휘와 색을 매핑한다.

의사코드로는 이게 전부다.

for (each cell i, j) {
  v = fbm(i * scale, j * scale, t);   // 시간축을 가진 노이즈 필드
  band = quantize(v);                 // 임계값으로 밴드 결정
  drawGlyph(glyphs[band], palette[band], i, j);
}
Grid Field Study — 시간축 노이즈 필드 위의 글리프 그리드새 탭에서 열기 ↗

구현 포인트

노이즈를 바닥부터

의존성을 없애기 위해 노이즈도 직접 만들었다. 정수 격자점을 비트 믹싱으로 해싱하는 hash3, 그걸 smoothstep으로 3선형 보간하는 3D 값 노이즈, 그리고 주파수를 올려가며 3옥타브를 합치는 fBm.

function fbm(x, y, z) {
  return (vnoise(x, y, z) * 0.62 +
          vnoise(x * 2.13 + 31, y * 2.13 + 17, z * 1.7) * 0.26 +
          vnoise(x * 4.31 + 57, y * 4.31 + 91, z * 2.9) * 0.12);
}

1옥타브만으로는 덩어리가 너무 밋밋하고, 옥타브를 더하자 경계가 원작처럼 지글거리기 시작했다.

임계값은 분포의 분위수에서

처음에는 0~1을 균등하게 9등분했는데, 화면이 원작과 전혀 다르게 나왔다. fBm의 출력은 0.5 근처에 몰린 종 모양 분포라, 균등 분할은 가운데 밴드만 비대하게 만든다. 임계값을 fBm 분포의 분위수에서 뽑아 각 밴드의 화면 점유율을 직접 고정하자(검은 여백 ~24% 등) 비로소 원작의 밀도 배분이 나왔다. 값이 아니라 면적을 디자인해야 했다.

등고선 = 도넛 사슬

이 작품의 시그니처는 영역 경계를 따라 구슬처럼 이어지는 도넛 사슬이다. 알고 보면 별도 로직이 아니라 양자화의 부산물이다. 아주 좁은 밴드(예: 0.465 ≤ v < 0.478)는 노이즈 필드의 등고선을 따라 폭 1셀짜리 계단형 띠로 나타나는데, 그 밴드에 도넛 글리프를 배정하면 등고선이 곧 사슬이 된다. marching squares 같은 걸 꺼낼 필요가 없었다.

제한이 만드는 통일감

팔레트는 검정/버밀리언/크림/토프 4색으로 제한하고, 글리프도 원·도넛·십자·줄무늬·사각 다섯 가지만 쓴다. 같은 밴드 안에서는 두 번째 노이즈 n2와 좌표 패리티 (i + j) & 1로 색과 크기를 변주한다. 규칙은 적고 전역적이라 화면 어디를 잘라도 같은 작품처럼 보이고, 변주는 국소적이라 지루하지 않다.

} else if (v < 0.478) {          // 등고선: 도넛 사슬
  gDonut(px, py, s, CREAM, RED);
} else if (v < 0.514) {          // 십자 필드
  gPlus(px, py, s, n2 < 0.4 ? TAUPE : n2 < 0.8 ? GREY : RED);
  if (!par) gCircle(px, py, s, n2 < 0.4 ? TAUPE : GREY, 0.09);
}

배운 것

  • 복잡해 보이는 화면의 뼈대는 한 줄이다. 필드 → 양자화 → 룩업. 풍부함은 파이프라인의 각 단계(옥타브, 분위수, 글리프 어휘)에 얹은 작은 결정들에서 나온다.
  • 분포를 모르면 임계값도 없다. 노이즈를 자를 때는 값의 범위가 아니라 값의 분포를 봐야 한다. 밴드의 화면 점유율이 곧 구도다.
  • 등고선은 공짜다. 좁은 밴드 하나가 marching squares를 대신한다. 양자화가 만드는 계단 아티팩트를 버그가 아니라 조형 언어로 쓰는 게 이 스타일의 핵심이다.
  • 제한이 스타일을 만든다. 4색과 5개 글리프라는 좁은 어휘가 오히려 화면 전체를 하나의 작품으로 묶는다.

다음 스터디에서는 다른 작가님의 작품으로 필드가 아닌 에이전트 기반 시스템을 뜯어볼 계획이다.

  • 원본 저장소: Lab02-CreativeCoding-Processing
  • 원작 스타일: @seohyo 작가님 — 멋진 작품을 만들어 주신 작가님께 존경을 담아. 학습 목적의 오마주이며 원작의 복제가 아니다