# 게임보이 컬러에 실시간 3D 셰이더를 구현하다

> Clean Markdown view of GeekNews topic #26529. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=26529](https://news.hada.io/topic?id=26529)
- GeekNews Markdown: [https://news.hada.io/topic/26529.md](https://news.hada.io/topic/26529.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-02-09T11:32:41+09:00
- Updated: 2026-02-09T11:32:41+09:00
- Original source: [blog.otterstack.com](https://blog.otterstack.com/posts/202512-gbshader/)
- Points: 1
- Comments: 1

## Topic Body

- 게임보이 컬러에서 **실시간 3D 셰이딩**을 구현한 프로젝트로, 플레이어가 빛의 궤도를 조작하며 물체를 회전시킬 수 있음  
- **정규화 벡터와 램버트 셰이딩(dot product)** 계산을 기반으로, 구면좌표계를 이용해 연산을 단순화함  
- **곱셈 명령이 없는 SM83 CPU**의 제약을 극복하기 위해 로그 변환과 룩업 테이블을 활용, 8비트 정밀도로 연산 수행  
- **자기 수정 코드(self-modifying code)** 를 사용해 약 10%의 성능 향상을 달성하고, 프레임당 15개의 타일을 렌더링함  
- AI를 활용한 코드 생성은 대부분 실패했으며, 핵심 알고리듬과 셰이더는 **직접 작성한 수작업 코드**로 완성됨  

---
### 프로젝트 개요
- 게임보이 컬러에서 **실시간으로 이미지를 렌더링하는 게임**을 제작  
  - 플레이어는 궤도 형태의 빛을 조작하며 물체를 회전시킴  
- 전체 코드는 GitHub 저장소([nukep/gbshader](https://github.com/nukep/gbshader))에서 공개됨  

### 3D 제작 과정
- **Blender**를 사용해 초기 룩 개발(lookdev)을 진행, 결과가 시각적으로 만족스러워 프로젝트를 진행함  
- **Cryptomatte**와 커스텀 셰이더를 이용해 **노멀맵(normal map)** 을 생성  
  - 찻주전자(teapot) 모델은 카메라를 회전시켜 PNG 시퀀스로 노멀맵을 출력  
  - 게임보이 컬러 모델의 화면 부분은 별도 장면으로 렌더링 후 합성  

### 수학적 기반
- 노멀맵은 각 픽셀의 **법선 벡터**를 인코딩하는 **벡터 필드**로 사용  
- **램버트 셰이딩**은 `v = N·L` 형태의 내적(dot product)으로 계산  
- 구면좌표계로 변환해 `v = sinNθ sinLθ cos(Nφ−Lφ) + cosNθ cosLθ` 형태로 단순화  
  - 모든 벡터의 반지름 r=1로 가정해 연산량을 줄임  

### 게임보이에서의 구현
- **Lθ(빛의 세로각)** 을 상수로 고정하고, **Lφ(빛의 회전각)** 만 플레이어가 조작  
- ROM에는 각 픽셀을 `(Nφ, log(m), b)` 형태로 저장  
- **곱셈 명령 부재**를 해결하기 위해 로그 변환과 룩업 테이블(`log`, `pow`)을 사용  
  - 부호(sign) 비트를 상위 비트에 저장해 음수 연산 지원  
- 모든 스칼라 값은 **-1.0~+1.0 범위의 8비트 분수**로 표현  
  - 덧셈은 선형 공간에서, 곱셈은 로그 공간에서 수행  
  - 127을 분모로 사용해 ±1을 모두 표현 가능하게 함  

### cos_log와 핵심 연산
- `cos_log`는 `log(cos x)` 형태의 결합 룩업으로, 곱셈을 로그 덧셈으로 대체  
- 픽셀당 연산량  
  - 뺄셈 1회, `cos_log` 조회 1회, 덧셈 1회, `pow` 조회 1회, 덧셈 1회  
  - 총 3회 덧셈/뺄셈, 2회 룩업 수행  

### 성능
- **프레임당 15개의 타일**을 처리, 일부 빈 행은 더 빠르게 계산  
- 픽셀당 약 **130 사이클**, 빈 행은 3 사이클 소요  
- CPU의 약 **89%** 가 셰이더 연산에 사용되며, 나머지는 입력 및 I/O 처리에 사용  

### 자기 수정 코드(Self-Modifying Code)
- 프레임당 약 960픽셀을 처리하는 핵심 루프를 최적화하기 위해 **명령어 자체를 수정**  
  - 상수를 직접 코드에 삽입해 변수 로드보다 빠른 연산 수행  
  - 예: `sub a, 8`이 `sub a, variable`보다 12사이클 빠름  
  - 전체적으로 약 **11,520 사이클(10%) 절감**  

### AI 활용 시도
- 전체 프로젝트의 **95%는 수작업**으로 작성  
- AI는 **Game Boy 어셈블리(SM83)** 작성에 어려움을 겪음  
- AI 사용 내역  
  - Python: OpenEXR 레이어 읽기  
  - Blender: 장면 자동화 스크립트  
  - SM83: 일부 기능 스니펫 (예: VRAM DMA)  
- 실패한 시도  
  - AI로 셰이더 어셈블리 코드 생성 시도 → 비효율적이고 오류 다수  
- Claude Sonnet 4 모델을 이용해 의사코드에서 어셈블리 생성 시도  
  - 일부 작동했으나 느리고, Z80과 SM83 혼동 등의 오류 발생  
  - 최종 코드는 수동으로 완전 재작성  

### 결론 및 교훈
- AI는 단순 스크립트에는 유용하지만, **정확성과 검증이 필수**  
- OpenEXR 처리 코드에서 AI가 **채널 정렬 오류(BGR vs RGB)** 를 일으켜 수주간 버그 발생  
- 경험을 통해 “AI 사용 시 검증이 가장 중요하다”는 교훈을 강조  
- 프로젝트는 **레거시 하드웨어의 한계를 극복한 실험적 셰이더 구현 사례**로 평가됨

## Comments



### Comment 50870

- Author: neo
- Created: 2026-02-09T11:32:41+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46935791) 
- 진짜 **해커 감성**의 글을 HN에서 보게 되어 반가운 마음임  
  - 단순히 AI 프롬프트로 만든 게 아닌가 궁금했음. 어떻게 구현했는지 알고 싶음 😉  

- 결과물이 정말 멋짐. 내가 이해하기로는 이건 “3D처럼 보이지만 실제로는 **2D 노멀맵**을 미리 렌더링해 조명 효과를 입힌 셰이더”임  
  프레임들은 [여기 GitHub 링크](https://github.com/nukep/gbshader/tree/main/sequences/gbspin_frames)에 있음  
  - 사실상 “진짜 3D” 렌더러와 크게 다르지 않음. **deferred 렌더링 파이프라인**에서도 깊이맵, 노멀맵, 컬러 버퍼 등 2D 버퍼 위에서 셰이더가 작동함.  
    3D 삼각형 처리 부분은 단순하게 유지하고, 비싼 조명 셰이더는 2D 이미지 위에서 한 번만 실행되므로 효율적임  
    셰이더 입장에서 입력이 3D 벡터라면 그건 3D 셰이더임. 3D 래스터라이저가 있느냐는 별개의 문제임  
    현대 3D 게임들도 이런 방식을 다양하게 활용함. 여러 시점에서 미리 렌더링한 모델을 사용하는 **imposter 기법**도 정식 3D 엔진에서 쓰이는 기술임  
  - 예전 **Mac 게임들**이 3D 가속 하드웨어 없이 2D 텍스처에 조명을 입히던 방식과 비슷함.  
    다만 이번엔 그게 Gameboy Color에서 돌아간다는 점이 놀라움  

- 안녕하세요, 작성자임. 여기에 글이 올라왔다고 들어서 계정을 만들었음. 공유해줘서 고마움  
  환경 맵을 이용해 더 단순화하는 실험도 진행 중이며, [Bsky에 공유한 링크](https://bsky.app/profile/dannyspencer.bsky.social/post/3mecu4zzkfc2n)에서 볼 수 있음  

- 정말 흥미로운 프로젝트임. 예전에 **C64 어셈블리 코딩**하던 시절이 떠오름.  
  당시에도 곱셈 명령이 없어서 하드웨어 제약을 우회하는 창의적인 방법을 찾아야 했음  

- AI를 사용해보려는 시도였지만 결과적으로는 실패한 실험이었음.  
  업계가 AI 얘기로 떠들썩해서 직접 체험해보고 싶었고, **생성형 AI 사용 여부를 투명하게 공개**하는 게 중요하다고 생각함.  
  숨기면 신뢰를 해치고, 공개하면 다른 의견을 가진 사람들과도 열린 대화를 할 수 있음  
  - 원래는 중립적인 어조였는데, 사람들이 내가 AI를 찬양한다고 오해해서 약간 회의적으로 바꿨음.  
    단지 이 과정을 기록하고 싶었을 뿐임  

- 이 GBC 셰이더는 “모든 계산은 제약 속의 **근사치**”라는 진리를 보여줌.  
  곱셈은 테이블 조회와 덧셈으로 대체되고, 정밀도는 눈으로 보이는 결과에 맞춰 조정됨  

- 진짜 감탄스러움. 특히 이게 실제 **Game Boy Color 하드웨어**에서 돌아간다는 점이 놀라움.  
  종종 카트리지에 강력한 프로세서를 넣고 GBC를 단순 터미널로 쓰는 경우가 많은데, 이건 그런 해킹이 아님  

- 솔직히 Nintendo가 **GBC나 GBA를 재출시**해줬으면 좋겠음.  
  몇 개의 게임을 내장한 카트리지 형태로 팔면 바로 살 의향이 있음  
  - 중고로는 꽤 저렴하게 구할 수 있음. 플래시 카트리지를 추가하면 끝임.  
    다만 요즘은 같은 폼팩터의 **안드로이드 휴대용 기기**가 더 실용적임.  
    나도 Gameboy 컬렉션이 있지만, 요즘은 에뮬레이터가 훨씬 편함  
  - Oculus VR 창업자가 만든 **ModRetro Chromatic**을 사면 됨.  
    Nintendo가 새로 만든다 해도 이만큼 좋을 순 없을 것 같음  

- 이런 글이야말로 HN이 존재하는 이유임.  
  예전 **기술 잡지**를 넘기던 때의 즐거움을 다시 느끼게 함  

- 이 작성자는 좋은 의미에서 **미친 천재**임
