
Ggyak
작성자
샌드폴 랩 — 물리 엔진 없이 셀룰러 오토마타로 8만 셀을 60fps로 굴린 픽셀 물리 시뮬레이터
💻 코드/앱2026년 7월 7일· 👁 12
외부 물리 엔진 하나 없이 셀룰러 오토마타를 직접 구현해, 384×216 그리드의 셀 8만 개가 매 프레임 갱신되면서도 60fps를 지킵니다.
자랑 포인트
- 외부 물리 엔진 없이 셀룰러 오토마타를 직접 구현 — 8만 셀을 매 프레임 갱신하면서도 60fps 유지
- Uint8Array·Uint16Array로 셀 상태를 표현해 객체 생성 0, ImageData 직접 쓰기 + putImageData 한 번으로 렌더링
- 물+불=증기, 용암+물=돌, 화약 연쇄 폭발까지 — 12원소가 프레임 단위로 상호작용하는 살아있는 픽셀 생태계
브라우저에서 모래를 한 줌 뿌리면 아래로 쏟아지고, 물은 바닥을 찾아 수평이 되고, 불은 나무를 타고 번집니다. 샌드폴 랩은 고전 falling-sand 장르를 웹에서 재현한 픽셀 물리 시뮬레이터입니다. 특별한 건 — 외부 물리 엔진을 전혀 쓰지 않았다는 점이에요. 384×216 그리드 위 8만 개의 셀을 셀룰러 오토마타 규칙만으로 매 프레임 직접 굴립니다.

주요 기능
- 12가지 원소, 진짜 같은 상호작용 — 모래·물·돌·나무·불·기름·화약·연기·증기·용암·산·씨앗. 물과 불이 만나면 증기가 피어오르고, 용암이 물에 닿으면 돌로 굳고, 씨앗은 물을 만나면 초록 줄기를 위로 밀어 올립니다.
- 프레임 단위로 굴러가는 연쇄 폭발 — 화약에 불이 닿는 순간 폭발 파동이 셀을 타고 퍼져 나갑니다. 한 번의 클릭이 화면 전체를 뒤집는 도미노가 돼요.
- 바로 만져보는 데모 씬 4종 — 기본 풍경 / 폭발 실험 / 용암 폭포 / 비 내리기. 빈 화면 앞에서 막막할 틈 없이 곧바로 실험을 시작할 수 있습니다.
- 원형 브러시 + 시뮬레이션 제어 — 1~30 크기 브러시로 드래그해 그리고, 우클릭으로 지우고, 일시정지·한 스텝 진행·0.5x/1x/2x 속도 조절까지. 레트로 CRT 스캔라인 무드도 토글할 수 있어요.
모바일 터치도 그대로 지원해서, 폰에서도 손끝으로 모래를 쏟아볼 수 있습니다.

기술 이야기
가장 큰 고민은 "8만 개 셀을 매 프레임 갱신하면서 어떻게 60fps를 지키느냐" 였습니다. 답은 자바스크립트 객체를 최대한 만들지 않는 것이었어요.
- 셀 상태는
Uint8Array(원소 id) +Uint16Array(수명/에너지) 로만 표현합니다. 셀마다 객체를 만들면 GC가 프레임을 잡아먹기 때문에, 원시 타입 배열로 메모리를 평평하게 눌렀습니다. - 렌더링은
ImageData버퍼에 픽셀을 직접 쓰고putImageData한 번으로 끝냅니다. DOM도, 수만 번의 canvas 드로잉 호출도 없이 한 번의 이미지 전송으로 화면을 갱신해요. - 편향 없는 시뮬레이션 — 셀을 항상 같은 방향으로 훑으면 모래가 한쪽으로 쏠립니다. 그래서 행은 아래→위로, 열 스캔 방향은 프레임마다 좌우를 번갈아 가고, 프레임 스탬프로 같은 셀이 한 프레임에 두 번 이동하는 걸 막았습니다.
- 난수도
Math.random()대신 xorshift32 를 인라인으로 돌립니다. 매 프레임 수만 번 호출되는 난수라 이 작은 차이가 프레임 예산에서 꽤 큰 몫을 차지했어요.
스택은 React 19 + TypeScript + Vite + Tailwind CSS 4. UI(원소 팔레트·컨트롤·HUD)는 React가 맡고, 시뮬레이션 루프는 React 바깥의 순수 타입드 배열 로직으로 분리해 렌더링과 물리를 깔끔하게 떼어 놨습니다.
마무리
물리 엔진을 가져다 쓰면 훨씬 쉬웠겠지만, "셀 하나하나가 왜 그렇게 움직이는지"를 직접 규칙으로 써 내려가는 과정 자체가 이 프로젝트의 재미였습니다. 브라우저만 있으면 설치 없이 바로 모래를 쏟아볼 수 있으니, 데모에서 한 번 부숴 보세요.