Skip to content

Commit 326a320

Browse files
committed
update: README.md
1 parent c260c77 commit 326a320

File tree

2 files changed

+71
-68
lines changed

2 files changed

+71
-68
lines changed

Guide/그래픽변환원리.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,23 @@
5353
* 결과: **0(완전 어두움) ~ 255(완전 밝음)** 사이의 값
5454

5555
### ④ 감마 보정 (Gamma Correction)
56-
문자 사이사이에 검은 여백이 있어서 화면이 원본보다 **어둡게 느껴집니다**.
57-
이를 보정하기 위해 밝기 값을 인위적으로 **밝게 조정**합니다.
58-
* 사용 감마: `0.35` (기본 1.0보다 밝게)
59-
* `gamma_table[i]`에 미리 계산된 보정 값을 저장해두고 즉시 조회합니다.
56+
문자마다 주변이 비어 있어 실제 픽셀보다 **어둡게 보일 수 있습니다**.
57+
이를 완화하려고 각 셀의 **RGB 색상**에 감마 LUT를 적용해 더 밝은 색을 사용합니다.
58+
* 사용 감마: `0.35` (눈에 보이는 색상을 밝게)
59+
* `gamma_table[i]`에 미리 계산된 보정 값을 저장해두고 r/g/b 채널마다 조회합니다.
6060

6161
### ⑤ 문자 매핑 (ASCII Mapping)
6262
최종 밝기 값에 해당하는 **ASCII 문자**를 선택합니다.
6363

6464
```
6565
밝기 스케일:
6666
어두움 ◀━━━━━━━━━━━━━━━━━━━━━━━▶ 밝음
67-
@ % # * + = - : . (공백)
67+
.:-=+*#%@ (왼쪽 공백)
6868
```
6969

70-
* **0 (칠흑)**: `@` (가장 촘촘한 문자)
70+
* **0 (칠흑)**: ` ` (공백, 가장 가벼운 문자)
7171
* **128 (중간)**: `+` 또는 `=`
72-
* **255 (눈부심)**: ` ` (공백, 빈 문자)
72+
* **255 (눈부심)**: `@` (가장 촘촘한 문자)
7373

7474
밝기→문자 변환도 **`idxLUT[brightness]`** 테이블로 미리 계산해두어 연산을 최소화합니다.
7575

README.md

Lines changed: 64 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,16 @@ Doom 게임을 웹에서 ASCII 아트로 즐길 수 있습니다.
3434
- 김철준: 아스키 그래픽 변환 로직 설계
3535

3636
5. 개발 중 어려웠던 점과 해결 방법
37-
- 팔레트/감마: 원본 팔레트와 ASCII 밝기 스케일이 달라 어둡게 보임 → 감마 LUT(0.35)와 밝기→문자 LUT(idxLUT) 재조정.
38-
- 해상도 스케일링: 셀 단위 다운샘플 시 계단/깨짐 → 적분영상 + 박스필터 평균으로 셀 컬러 추출.
39-
- 메모리/성능: 프레임마다 동적 할당이 있어 힙 성장 → 프리할로케이션 버퍼(temp_r/g/b 등)와 역수 LUT로 나눗셈 제거.
37+
- WASM 포팅 & SDL 렌더링 흐름 파악
38+
- Doom이 `screens[]` 프레임버퍼를 SDL로 넘기고, Emscripten이 이를 `<canvas>`에 매핑하는 전 과정을 따라가야 원시 RGBA 데이터를 확보할 수 있었다.
39+
- JS에서 WebAssembly 메모리를 읽을 때 heap view가 언제 무효화되는지까지 이해해야 안정적으로 훅을 걸 수 있어, SDL 경로와 소프트웨어 렌더링 경로를 분리 조사하고 직접 프레임버퍼 hook을 구현했다.
40+
41+
- ASCII 변환 파이프라인 설계
42+
- 엔진은 320×200 RGBA 프레임을 내보내지만 목표 출력은 240×80 문자 격자로, 매 프레임 `Raw RGBA → 다운샘플 → 셀 평균 → 밝기/문자 결정 → 색상 보정`을 수행해야 했다.
43+
- 셀마다 픽셀을 순회하는 방식은 너무 느려서 Summed Area Table(적분영상)과 역수 LUT로 평균을 O(1)에 계산하고, SIMD 가능한 구간에 WASM SIMD128을 적용해 네 셀씩 동시에 밝기를 산출하도록 구조화했다.
44+
- 덕분에 “문자 기반 렌더링을 게임 엔진 프레임레이트로 유지하려면?”이라는 숙제를 알고리즘+저수준 최적화 조합으로 풀 수 있었다.
45+
46+
4047

4148
6. 가산점 항목으로 생각하는 부분
4249
- **SIMD 최적화 시도**: WASM SIMD128 인트린식을 사용하여 픽셀 처리 파이프라인 병렬화.
@@ -47,7 +54,6 @@ Doom 게임을 웹에서 ASCII 아트로 즐길 수 있습니다.
4754
- WASM이 네이티브에 준하는 성능을 내고 있음을 확인하는 대조군으로 활용.
4855

4956
7. Latency 측정 테이블
50-
5157
> **측정 기준**: RGBA 버퍼 입력 시점부터 ASCII 버퍼 출력 완료 시점까지의 **순수 알고리즘 연산 시간**
5258
> - **C++**: `I_ConvertRGBAtoASCII` (적분영상 생성 → 2-Pass 변환(SIMD 최적화 구조))
5359
> - **JavaScript**: `convertRGBAtoASCII_JS` (적분영상 생성 → 1-Pass 변환)
@@ -59,42 +65,32 @@ Doom 게임을 웹에서 ASCII 아트로 즐길 수 있습니다.
5965
| C++ SIMD OFF | 34.96 | 0.47 ms | 0.10 ms | 1.40 ms | MacOS / Apple M3 Pro / 36GB RAM / Chrome |
6066
| JavaScript | 27.32 | 0.56 ms | 0.40 ms | 1.10 ms | MacOS / Apple M3 Pro / 36GB RAM / Chrome |
6167

68+
## ⚙️ 동작 방식
6269

70+
### 아키텍처
6371

64-
## 🎮 특징
65-
66-
- 🌐 **브라우저에서 바로 실행**: 별도 설치 없이 웹 브라우저에서 바로 플레이
67-
- 🎨 **ASCII 아트 렌더링**: 터미널 스타일의 고유한 비주얼 경험
68-
- 📦 **WebAssembly 기반**: 네이티브에 가까운 성능으로 실행
69-
- 🚀 **자동 배포**: GitHub Actions를 통한 CI/CD 파이프라인
70-
- 🐳 **Docker 기반 빌드**: 일관된 빌드 환경 제공
71-
72-
73-
## 🛠️ 기술 스택
74-
75-
### 핵심 기술
76-
77-
- **[Emscripten](https://emscripten.org/)**: C/C++ 코드를 WebAssembly와 JavaScript로 컴파일
78-
- **[WebAssembly (WASM)](https://webassembly.org/)**: 고성능 바이너리 포맷으로 네이티브에 가까운 성능 제공
79-
- **[SDL2](https://www.libsdl.org/)**: 크로스 플랫폼 멀티미디어 라이브러리 (입력, 오디오, 네트워킹)
80-
- **[Chocolate Doom](https://www.chocolate-doom.org/)**: 정확한 Doom 소스 포트
81-
82-
### 빌드 도구
83-
84-
- **Autotools** (autoconf, automake): 빌드 시스템 자동화
85-
- **Docker**: 일관된 빌드 환경 제공
86-
- **GitHub Actions**: 자동 빌드 및 배포
87-
88-
### Emscripten 기능
72+
```mermaid
73+
flowchart TB
74+
subgraph browser["Web Browser"]
75+
ui["HTML / JS<br/>UI & Controls"]
76+
canvas["Canvas / Audio / Inputs<br/>(브라우저 API)"]
77+
end
8978
90-
- `ASYNCIFY`: 동기 C 코드를 비동기 JavaScript로 변환
91-
- `ALLOW_MEMORY_GROWTH`: 동적 메모리 할당 지원
92-
- `FORCE_FILESYSTEM`: Emscripten 가상 파일 시스템으로 WAD 파일 로드
93-
- `USE_SDL=2`: SDL2 바인딩을 통한 브라우저 API 접근
94-
- `EXPORTED_RUNTIME_METHODS`: JavaScript에서 WebAssembly 함수 호출을 위한 런타임 메서드 노출
95-
- **WASM SIMD**: ASCII 렌더링 성능 최적화를 위한 SIMD 명령어 사용 (`i_ascii.cpp`)
79+
subgraph wasm["WASM (Emscripten)"]
80+
logic["게임 로직 (C)<br/>Chocolate Doom"]
81+
ascii["ASCII 렌더링 엔진 (C++)<br/>i_ascii.cpp · 픽셀→문자 매핑"]
82+
sdl["SDL2 포팅 레이어<br/>브라우저 API 브릿지"]
83+
fs["Emscripten FS<br/>WAD / Saves (IndexedDB 백엔드)"]
84+
end
9685
97-
## ⚙️ 동작 방식
86+
ui <--> logic
87+
logic --> ascii
88+
ascii --> sdl
89+
logic --> sdl
90+
sdl <--> canvas
91+
logic <--> fs
92+
ascii --> fs
93+
```
9894

9995
### 빌드 프로세스
10096

@@ -125,31 +121,6 @@ WebAssembly (.wasm) + JavaScript (.js) + HTML (.html)
125121
- ASCII 아트 렌더링 엔진이 게임 화면을 터미널 스타일로 변환
126122
- Canvas API를 통해 브라우저에 렌더링
127123

128-
### 아키텍처
129-
130-
```mermaid
131-
flowchart TB
132-
subgraph browser["Web Browser"]
133-
ui["HTML / JS<br/>UI & Controls"]
134-
canvas["Canvas / Audio / Inputs<br/>(브라우저 API)"]
135-
end
136-
137-
subgraph wasm["WASM (Emscripten)"]
138-
logic["게임 로직 (C)<br/>Chocolate Doom"]
139-
ascii["ASCII 렌더링 엔진 (C++)<br/>i_ascii.cpp · 픽셀→문자 매핑"]
140-
sdl["SDL2 포팅 레이어<br/>브라우저 API 브릿지"]
141-
fs["Emscripten FS<br/>WAD / Saves (IndexedDB 백엔드)"]
142-
end
143-
144-
ui <--> logic
145-
logic --> ascii
146-
ascii --> sdl
147-
logic --> sdl
148-
sdl <--> canvas
149-
logic <--> fs
150-
ascii --> fs
151-
```
152-
153124
### ASCII 그래픽 변환 흐름
154125

155126
```text
@@ -172,6 +143,30 @@ SDL Framebuffer (RGBA32) 입력
172143
JS가 HEAPU8 버퍼를 읽어 Canvas `fillText`로 렌더
173144
```
174145

146+
## 🛠️ 기술 스택
147+
148+
### 핵심 기술
149+
150+
- **[Emscripten](https://emscripten.org/)**: C/C++ 코드를 WebAssembly와 JavaScript로 컴파일
151+
- **[WebAssembly (WASM)](https://webassembly.org/)**: 고성능 바이너리 포맷으로 네이티브에 가까운 성능 제공
152+
- **[SDL2](https://www.libsdl.org/)**: 크로스 플랫폼 멀티미디어 라이브러리 (입력, 오디오, 네트워킹)
153+
- **[Chocolate Doom](https://www.chocolate-doom.org/)**: 정확한 Doom 소스 포트
154+
155+
### 빌드 도구
156+
157+
- **Autotools** (autoconf, automake): 빌드 시스템 자동화
158+
- **Docker**: 일관된 빌드 환경 제공
159+
- **GitHub Actions**: 자동 빌드 및 배포
160+
161+
### Emscripten 기능
162+
163+
- `ASYNCIFY`: 동기 C 코드를 비동기 JavaScript로 변환
164+
- `ALLOW_MEMORY_GROWTH`: 동적 메모리 할당 지원
165+
- `FORCE_FILESYSTEM`: Emscripten 가상 파일 시스템으로 WAD 파일 로드
166+
- `USE_SDL=2`: SDL2 바인딩을 통한 브라우저 API 접근
167+
- `EXPORTED_RUNTIME_METHODS`: JavaScript에서 WebAssembly 함수 호출을 위한 런타임 메서드 노출
168+
- **WASM SIMD**: ASCII 렌더링 성능 최적화를 위한 SIMD 명령어 사용 (`i_ascii.cpp`)
169+
175170
## 📋 Prerequisites
176171

177172
**Docker Desktop만 설치하면 됩니다** (모든 플랫폼: macOS, Windows, Linux)
@@ -231,6 +226,14 @@ python3 -m http.server 8000
231226

232227
브라우저에서 `http://localhost:8000` 열기
233228

229+
## 🎮 특징
230+
231+
- 🌐 **브라우저에서 바로 실행**: 별도 설치 없이 웹 브라우저에서 바로 플레이
232+
- 🎨 **ASCII 아트 렌더링**: 터미널 스타일의 고유한 비주얼 경험
233+
- 📦 **WebAssembly 기반**: 네이티브에 가까운 성능으로 실행
234+
- 🚀 **자동 배포**: GitHub Actions를 통한 CI/CD 파이프라인
235+
- 🐳 **Docker 기반 빌드**: 일관된 빌드 환경 제공
236+
234237
## 📚 참고 자료
235238

236239
- [Chocolate Doom 공식 사이트](https://www.chocolate-doom.org/)

0 commit comments

Comments
 (0)