Appearance
渲染管线 (Rendering Pipeline)
GBA 的 240×160 像素画面是如何重现的?pokeemerald-wasm 在 WASM 模块内部(
src/wasm_display.c)用 C 实现了完整的 GBA 图形渲染管线——从 VRAM 中的 Tile 解码、到 OAM 精灵叠加、再到 BGR555 调色板转换为 RGBA,合成出一张 240×160 的 RGBA 帧缓冲区。宿主端(浏览器app.js或原生前端)只负责把这快缓冲区搬运到屏幕上。
架构演进
重大架构变更(2026-07 上游同步)
早期版本中,整条渲染管线(Tile 解码、精灵叠加、调色板转换、Canvas 写入)都由 web/app.js 用 JavaScript 实现。上游已把全部 PPU 逻辑搬进 WASM 模块本身,新增 src/wasm_display.c(#if WASM 守卫)。这是一次本质性的架构转变:
- 渲染下沉到 WASM:
WasmRenderFrame()在模块内部合成完整 RGBA 帧,WasmDisplayBuffer()返回缓冲区指针。 - 宿主退化为「搬运工」:浏览器
app.js的render()现在只有两行——调用WasmRenderFrame(),再ctx.putImageData()把 RGBA 搬上 Canvas。 - 一份渲染器,多个前端:同一套渲染逻辑同时服务于浏览器、原生 Raylib 前端、Kindle 帧缓冲前端,因为它们都消费同一个 RGBA 缓冲区。
本主题下文统一以 src/wasm_display.c 的 C 实现为基准讲解。
宿主 / WASM 渲染分工
涵盖内容
| 章节 | 核心主题 |
|---|---|
| 渲染概念 | 渲染管线流程、BG 模式、Tile 解码、精灵渲染、调色板转换、HBlank DMA 扫描线 |
| 练习 | 像素追踪、OAM 属性分析、性能估算 |
| 代码走读 | wasm_display.c 渲染相关函数逐段解读 |
核心概念
wasm_display.c 完整模拟了 GBA 的 PPU(Picture Processing Unit),在 C 中实现了以下功能:
- 背景渲染:支持 GBA Mode 0(4 个文字背景层)、Mode 1(2 文字 + 1 仿射)、Mode 2(2 仿射)、Mode 3/4(位图模式),通过读取 VRAM 中的 Tile 数据和 Tile Map 组合像素
- 精灵渲染:读取 OAM 中 128 个精灵的属性(位置、大小、Tile 索引、优先级),支持仿射变换(旋转/缩放)和翻转
- 调色板转换:将 GBA 的 BGR555(15 位色)格式转换为 RGBA8888 格式,写入模块内的静态缓冲区
- 特效处理:Window 遮罩、Alpha 混合、亮度增减等半透明效果
- 优先级系统:BG 层和精灵按优先级值(0-3)交替合成,确保正确的遮挡关系
- HBlank DMA 扫描线:采样每条扫描线上的 GPU 寄存器值(如逐行滚屏、逐行变色),还原真实硬件的扫描线效果
前置知识
- 基本图形学概念(像素、分辨率、颜色深度)
- WASM 内存模型 — 理解 VRAM、OAM、Palette 的内存地址
- GBA 硬件模拟 — 理解 DISPCNT 等 I/O 寄存器的作用
- 源码兼容与适配 — 理解
#if WASM守卫如何隔离渲染代码
学习路径
→ 下一步:构建与部署