193 lines
6.4 KiB
Markdown
193 lines
6.4 KiB
Markdown
# IMX6U-Game
|
||
|
||
一个从 CPU 软光栅化渲染器向嵌入式游戏图形库迁移的项目。
|
||
|
||
核心目标是在 IMX6U(ARM 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 (交叉编译) | `/dev/fb0` 直接写屏 | 最终在 IMX6U 开发板上运行的版本 |
|
||
|
||
**为什么分三套?**
|
||
|
||
- **Windows 编译**:开发主力机通常是 Windows,有 IDE 调试、有图形窗口,渲染算法对不对一眼就能看到。这个阶段完全不关心嵌入式细节。
|
||
- **Linux x86 编译**:验证代码在 GCC/Clang 下有无警告、CMake 配置是否跨平台、系统 SDL2 依赖是否正确。很多嵌入式工具链的问题在 x86 Linux 上就能提前暴露。
|
||
- **ARM 交叉编译**:最终在 IMX6U 上跑。这个版本去掉 SDL2,直接 mmap `/dev/fb0` 写屏,减少依赖和内存开销。
|
||
|
||
## 构建说明
|
||
|
||
### 通用前置
|
||
|
||
```bash
|
||
# 克隆仓库后,确保子目录完整
|
||
cd IMX6U-Game
|
||
```
|
||
|
||
### Windows(Visual Studio / MSVC)
|
||
|
||
仓库已自带 SDL2 开发库(`libs/Win/SDL2`),无需额外安装。
|
||
|
||
```bash
|
||
cmake -B build-win .
|
||
cmake --build build-win --config Release
|
||
```
|
||
|
||
运行:
|
||
```bash
|
||
./build-win/Release/IMX6U-Game.exe
|
||
```
|
||
|
||
### Linux x86_64(Ubuntu / WSL2)
|
||
|
||
需要系统 SDL2:
|
||
|
||
```bash
|
||
sudo apt-get install libsdl2-dev cmake g++
|
||
```
|
||
|
||
构建:
|
||
```bash
|
||
cmake -B build-linux .
|
||
cmake --build build-linux
|
||
```
|
||
|
||
运行:
|
||
```bash
|
||
./build-linux/IMX6U-Game
|
||
```
|
||
|
||
### ARM 交叉编译(IMX6U)
|
||
|
||
需要交叉编译工具链:
|
||
|
||
```bash
|
||
sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
|
||
```
|
||
|
||
构建(启用 Framebuffer 后端):
|
||
```bash
|
||
cmake -B build-arm \
|
||
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm-linux-gnueabihf.cmake \
|
||
-DUSE_FRAMEBUFFER=ON .
|
||
cmake --build build-arm
|
||
```
|
||
|
||
部署到开发板:
|
||
```bash
|
||
scp build-arm/IMX6U-Game root@imx6u:/tmp/
|
||
```
|
||
|
||
板子上运行(需要 root 权限访问 `/dev/fb0`):
|
||
```bash
|
||
sudo /tmp/IMX6U-Game
|
||
```
|
||
|
||
ARM 版本启动后会打印 framebuffer 参数(分辨率、bpp、像素格式)。按 `q` 键或 `Ctrl+C` 退出。
|
||
|
||
## 显示后端架构
|
||
|
||
显示层通过抽象接口 `Platform::IDisplay` 与渲染逻辑解耦:
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ 游戏/渲染逻辑(Camera、Rasterizer 等) │
|
||
├──────────────────────────────────────┤
|
||
│ Core::FrameBuffer(CPU 颜色缓冲区) │
|
||
├──────────────────────────────────────┤
|
||
│ Platform::IDisplay │
|
||
│ - SDLDisplay : SDL2 窗口(PC) │
|
||
│ - FBDisplay : /dev/fb0(ARM) │
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
切换后端不需要修改任何渲染代码,只需要在 CMake 配置时开关 `USE_FRAMEBUFFER`。
|
||
|
||
## 目录结构
|
||
|
||
```text
|
||
IMX6U-Game/
|
||
├─ cmake/
|
||
│ └─ toolchain-arm-linux-gnueabihf.cmake # ARM 交叉编译工具链
|
||
├─ libs/
|
||
│ └─ Win/
|
||
│ ├─ SDL2/ # Windows 用 SDL2 库(头文件 + lib + DLL)
|
||
│ └─ SDL_image/ # SDL2_image 库(头文件 + lib + DLL)
|
||
├─ src/
|
||
│ ├─ Platform/
|
||
│ │ ├─ Display.h # 显示抽象接口
|
||
│ │ ├─ SDLDisplay.cpp # SDL2 窗口后端
|
||
│ │ └─ FBDisplay.cpp # Linux Framebuffer 后端
|
||
│ ├─ Core/
|
||
│ │ ├─ FrameBuffer.h/.cpp # CPU 颜色缓冲
|
||
│ │ ├─ DepthBuffer.h/.cpp # 深度缓冲
|
||
│ │ └─ Renderer.h/.cpp # 渲染调度(预留)
|
||
│ ├─ Math/
|
||
│ │ ├─ Vector2.h / Vector3.h / Vector4.h
|
||
│ │ ├─ Matrix4x4.h
|
||
│ │ └─ MathUtil.h
|
||
│ ├─ Rasterizer/
|
||
│ │ ├─ Rasterizer.h/.cpp # 线段光栅化
|
||
│ │ └─ TriangleRasterizer.h/.cpp # 三角形填充
|
||
│ ├─ RenderData/
|
||
│ │ ├─ Color.h
|
||
│ │ ├─ BoundingBox.h
|
||
│ │ └─ Triangle.h
|
||
│ ├─ Scene/
|
||
│ │ ├─ Camera.h/.cpp
|
||
│ │ ├─ Vertex.h / Mesh.h / Model.h / Transform.h
|
||
│ ├─ Asset/
|
||
│ │ └─ ObjLoader.h/.cpp # OBJ 模型加载(预留)
|
||
│ ├─ Shading/
|
||
│ │ └─ BlinnPhongShader.h/.cpp # 着色(预留)
|
||
│ ├─ test_fb.cpp # 独立 fb 测试(最小示例)
|
||
│ └─ main.cpp
|
||
├─ CMakeLists.txt
|
||
└─ README.md
|
||
```
|
||
|
||
## 模块说明
|
||
|
||
### Core
|
||
- **FrameBuffer**:CPU 侧颜色缓冲,渲染结果先写在这里
|
||
- **DepthBuffer**:深度测试用 Z-buffer
|
||
|
||
### Math
|
||
- 通用数学类型:`Vector2/3/4`、`Matrix4x4`
|
||
- 纯头文件实现,无动态分配
|
||
|
||
### Rasterizer
|
||
- **Rasterizer**:Bresenham 线段光栅化
|
||
- **TriangleRasterizer**:扫描线三角形填充 + 深度测试
|
||
|
||
### Platform
|
||
- **IDisplay**:显示后端抽象,解耦渲染与输出
|
||
- **SDLDisplay**:PC 端用 SDL2 窗口实时查看效果
|
||
- **FBDisplay**:ARM 端直接写 `/dev/fb0`
|
||
|
||
## 当前状态与后续
|
||
|
||
**已完成:**
|
||
- 可旋转立方体的 3D 渲染(MVP 变换、背面剔除、扫描线填充、深度测试)
|
||
- 双平台显示后端(SDL2 / Framebuffer)
|
||
- C++11 兼容代码
|
||
- CMake 跨平台构建
|
||
|
||
**待完成(按优先级):**
|
||
1. FrameBuffer 性能优化(`memset` 清屏、去掉 `at()`、定点数/NEON)
|
||
2. 输入抽象(键盘/触摸屏 evdev)
|
||
3. 纹理贴图
|
||
4. 2D 游戏层封装(Sprite、Tilemap)
|
||
5. OBJ 模型加载与完整光照
|
||
|
||
## 说明
|
||
|
||
- 代码标准:**C++11**,确保兼容嵌入式老工具链
|
||
- `test_fb.cpp` 是一个完全独立的 Linux framebuffer 最小测试,不依赖项目其他代码,用于快速验证板子显示通路
|
||
- Windows 和 Linux x86 版本共享 `SDLDisplay`,ARM 版本单独使用 `FBDisplay`
|