연재 크리에이티브 코딩 랩 일지

약 1분

@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 작가님 — 멋진 작품을 만들어 주신 작가님께 존경을 담아. 학습 목적의 오마주이며 원작의 복제가 아니다