Go to file
SepComet a051f6da4c 整理文件结构目录,Gfx 里放底层图形库相关函数,Apps 放上层的应用(启动器、游戏) 2026-06-06 17:31:19 +08:00
cmake init 2026-06-05 17:55:22 +08:00
docs 制订规范 2026-06-06 17:10:47 +08:00
libs/Win init 2026-06-05 17:55:22 +08:00
src 整理文件结构目录,Gfx 里放底层图形库相关函数,Apps 放上层的应用(启动器、游戏) 2026-06-06 17:31:19 +08:00
.gitattributes init 2026-06-05 17:55:22 +08:00
.gitignore 制订规范 2026-06-06 17:10:47 +08:00
CMakeLists.txt 整理文件结构目录,Gfx 里放底层图形库相关函数,Apps 放上层的应用(启动器、游戏) 2026-06-06 17:31:19 +08:00
CMakeSettings.json init 2026-06-05 17:55:22 +08:00
README.md 整理文件结构目录,Gfx 里放底层图形库相关函数,Apps 放上层的应用(启动器、游戏) 2026-06-06 17:31:19 +08:00

README.md

IMX6U-Game

一个从 CPU 软光栅化渲染器向嵌入式游戏图形库迁移的项目。

核心目标是在 IMX6UARM Cortex-A7无 GPU 或极弱 GPU上运行纯 CPU 渲染的 2D/3D 图形。为此,代码保持 C++11 兼容显示后端可切换SDL2 窗口 vs Linux Framebuffer以支持跨平台开发和嵌入式部署。

编译目标与验证目的

本项目支持三套编译目标,分别对应开发流程的不同阶段:

目标平台 显示后端 验证目的
Windows (x86/x64) SDL2 窗口 验证渲染逻辑、算法正确性、快速迭代调试
Linux x86_64 SDL2 窗口 验证 Linux 兼容性、CMake 构建、SDL2 系统依赖
ARM Linux (交叉编译) SDL2 或 /dev/fb0 最终在 IMX6U 开发板上运行的版本;优先目标以后续实际部署后端为准

为什么分三套?

  • Windows 编译:开发主力机通常是 Windows有 IDE 调试、有图形窗口,渲染算法对不对一眼就能看到。这个阶段完全不关心嵌入式细节。
  • Linux x86 编译:验证代码在 GCC/Clang 下有无警告、CMake 配置是否跨平台、系统 SDL2 依赖是否正确。很多嵌入式工具链的问题在 x86 Linux 上就能提前暴露。
  • ARM 交叉编译:最终在 IMX6U 上跑。若目标板使用 SDL2则 SDL2 仅作为显示/输入/计时适配层,核心渲染仍按 CPU framebuffer + 一次性提交设计;如需极简依赖,也保留 /dev/fb0 后端作为对照。

开发规范与性能红线

IMX6U 运行时性能预算较紧,后续开发必须遵守 docs/DEVELOPMENT_GUIDELINES.md。如果目标板使用 SDL2仍然要把 SDL2 限制在平台适配层,核心逻辑和渲染热路径不直接依赖 SDL

  • 核心逻辑和热路径默认不新增 float / double,需要小数时使用项目统一定点数;只在显示、调试、导入导出等边界层转换成浮点。
  • 主循环、每对象、每三角形/顶点/像素级代码中不得频繁创建 std::vector / std::string 等动态分配容器,应复用缓冲或使用固定容量结构。
  • PC/SDL 版本用于调试验证,不能把调试便利写法扩散到 ARM release 核心路径。
  • SDL2 后端只做显示、输入、计时和最终 framebuffer 提交,不在核心渲染/游戏逻辑中直接调用 SDL API。
  • 新增核心代码前按规范文档中的检查清单自查。

应用层与图形库拆分

项目后续按“两个游戏 + 一个启动器 + 一套底层图形库”组织,详细边界见 docs/APP_AND_GFX_ARCHITECTURE.md

  • Gfx / 底层图形库:只提供 framebuffer、SDL2/fb0 平台适配、输入/时间源、基础绘制能力例如点、线、矩形、四边形、sprite、tile。
  • Apps/Launcher:负责游戏选择、全局设置和启动流程。
  • Apps/GameAApps/GameB:分别维护自己的游戏规则、状态、资源和渲染调用。
  • Shared:只放应用层共享但不属于底层图形库的 UI、存档、配置、资源索引等。
  • 依赖方向必须保持 Apps -> Shared -> Gfx -> Platform,底层图形库不能反向依赖具体游戏。

初期推荐单进程多应用模式Launcher、GameA、GameB 共用同一个 SDL2 初始化、framebuffer 和主循环,通过统一 IApp 接口切换当前应用。

构建说明

通用前置

# 克隆仓库后,确保子目录完整
cd IMX6U-Game

WindowsVisual Studio / MSVC

仓库已自带 SDL2 开发库(libs/Win/SDL2),无需额外安装。

cmake -B build-win .
cmake --build build-win --config Release

运行:

./build-win/Release/IMX6U-Game.exe

Linux x86_64Ubuntu / WSL2

需要系统 SDL2

sudo apt-get install libsdl2-dev cmake g++

构建:

cmake -B build-linux .
cmake --build build-linux

运行:

./build-linux/IMX6U-Game

ARM 交叉编译IMX6U

需要交叉编译工具链:

sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf

本项目 ARM 端保留两类后端:

  • SDL2 后端目标是后续游戏主路径SDL2 负责显示、输入、计时和最终 framebuffer 提交。
  • Framebuffer 后端:作为极简依赖和显示通路对照测试。

构建Framebuffer 对照后端):

cmake -B build-arm-fb \
    -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm-linux-gnueabihf.cmake \
    -DUSE_FRAMEBUFFER=ON .
cmake --build build-arm-fb

构建SDL2 后端,要求工具链/sysroot 可找到目标板 SDL2 开发库):

cmake -B build-arm-sdl \
    -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm-linux-gnueabihf.cmake \
    -DUSE_FRAMEBUFFER=OFF .
cmake --build build-arm-sdl

部署到开发板:

scp build-arm-sdl/IMX6U-Game root@imx6u:/tmp/
# 或部署 framebuffer 对照版本:
scp build-arm-fb/IMX6U-Game root@imx6u:/tmp/

板子上运行:

/tmp/IMX6U-Game

Framebuffer 对照版本可能需要 root 权限访问 /dev/fb0。SDL2 版本是否需要额外环境变量或权限,取决于目标板 SDL2 视频驱动和显示栈配置。

显示后端架构

显示层通过抽象接口 Platform::IDisplay 与渲染逻辑解耦。后续应用层和图形库拆分后,Platform 会收敛到 Gfx 的平台适配层:

┌──────────────────────────────────────────────┐
│ AppsLauncher / GameA / GameB               │
├──────────────────────────────────────────────┤
│ SharedUI、存档、配置、资源索引              │
├──────────────────────────────────────────────┤
│ GfxDrawContext、FrameBuffer、Draw2D、Math   │
├──────────────────────────────────────────────┤
│ Platform::IDisplay                           │
│  - SDLDisplay : SDL2 显示/输入/计时适配       │
│  - FBDisplay  : /dev/fb0 对照后端             │
└──────────────────────────────────────────────┘

切换显示后端不应影响应用层和核心绘制逻辑;当前 CMake 通过 USE_FRAMEBUFFER 在 SDL2 与 framebuffer 后端间切换。

目录结构

当前源码仍处于早期验证布局:

IMX6U-Game/
├─ cmake/
│  └─ toolchain-arm-linux-gnueabihf.cmake  # ARM 交叉编译工具链
├─ libs/
│  └─ Win/
│     ├─ SDL2/                             # Windows 用 SDL2 库(头文件 + lib + DLL
│     └─ SDL_image/                        # SDL2_image 库(头文件 + lib + DLL
├─ src/
│  ├─ Platform/                            # 当前显示后端适配,后续归入 Gfx/Platform
│  ├─ Core/                                # FrameBuffer、DepthBuffer 等,后续归入 Gfx/Core
│  ├─ Math/                                # 当前 float 数学类型,后续补定点数并归入 Gfx/Math
│  ├─ Rasterizer/                          # 当前软光栅化代码,后续归入 Gfx/Draw2D 或 Gfx/Rasterizer
│  ├─ RenderData/                          # Color、Triangle 等基础渲染数据
│  ├─ Scene/                               # 当前 3D demo 场景数据
│  ├─ Asset/                               # 资源加载预留
│  ├─ Shading/                             # 着色预留
│  ├─ test_fb.cpp                          # 独立 fb 测试(最小示例)
│  └─ main.cpp                             # 当前 demo 入口,后续拆成 App 主循环
├─ docs/
│  ├─ DEVELOPMENT_GUIDELINES.md            # IMX6U 性能红线
│  └─ APP_AND_GFX_ARCHITECTURE.md          # 应用层与图形库分层
├─ CMakeLists.txt
└─ README.md

目标布局见 docs/APP_AND_GFX_ARCHITECTURE.md:后续会收敛为 src/Gfxsrc/Apps/Launchersrc/Apps/GameAsrc/Apps/GameBsrc/Shared

模块说明

Core

  • FrameBufferCPU 侧颜色缓冲,渲染结果先写在这里
  • DepthBuffer:深度测试用 Z-buffer

Math

  • 通用数学类型:Vector2/3/4Matrix4x4
  • 纯头文件实现,无动态分配

Rasterizer

  • RasterizerBresenham 线段光栅化
  • TriangleRasterizer:扫描线三角形填充 + 深度测试

Platform

  • IDisplay:显示后端抽象,解耦渲染与输出
  • SDLDisplaySDL2 后端PC 调试和 IMX6U SDL2 目标路径共用这一类适配思想
  • FBDisplay/dev/fb0 对照后端,用于极简显示通路验证

当前状态与后续

已完成:

  • 可旋转立方体的 3D 渲染MVP 变换、背面剔除、扫描线填充、深度测试)
  • 双平台显示后端SDL2 / Framebuffer
  • C++11 兼容代码
  • CMake 跨平台构建

待完成(按优先级):

  1. FrameBuffer 性能优化(memset 清屏、去掉 at()、定点数/NEON
  2. 应用层拆分Launcher / GameA / GameB / Shared和统一 IApp 主循环
  3. SDL2 输入抽象(键盘/触摸/按键状态快照)
  4. Gfx 基础 2D 绘制接口矩形、四边形、Sprite、Tilemap
  5. 纹理贴图、OBJ 模型加载与完整光照

说明

  • 代码标准:C++11,确保兼容嵌入式老工具链
  • test_fb.cpp 是一个完全独立的 Linux framebuffer 最小测试,不依赖项目其他代码,用于快速验证板子显示通路
  • Windows、Linux x86 和目标板 SDL2 路径共享 SDLDisplay 适配思想;FBDisplay 保留为 framebuffer 对照后端