Skip to content

渲染管线 (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.jsJavaScript 实现。上游已把全部 PPU 逻辑搬进 WASM 模块本身,新增 src/wasm_display.c#if WASM 守卫)。这是一次本质性的架构转变:

  • 渲染下沉到 WASMWasmRenderFrame() 在模块内部合成完整 RGBA 帧,WasmDisplayBuffer() 返回缓冲区指针。
  • 宿主退化为「搬运工」:浏览器 app.jsrender() 现在只有两行——调用 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 寄存器值(如逐行滚屏、逐行变色),还原真实硬件的扫描线效果

前置知识

学习路径

→ 下一步:构建与部署