更新文档
This commit is contained in:
parent
0fdcb6b8ff
commit
189072ba4e
62
README.md
62
README.md
|
|
@ -167,14 +167,10 @@ Framebuffer 对照版本可能需要 root 权限访问 `/dev/fb0`。SDL2 版本
|
||||||
|
|
||||||
项目运行时不依赖 PNG/TTF 解码库。图片和字体资源在离线阶段转换成 C++ 头文件,但运行时格式按资源类型区分:
|
项目运行时不依赖 PNG/TTF 解码库。图片和字体资源在离线阶段转换成 C++ 头文件,但运行时格式按资源类型区分:
|
||||||
|
|
||||||
- sprite / atlas:`uint16_t` `RGBA5551`
|
- sprite / atlas:`uint16_t` `RGBA5551`(5-bit R/G/B + 1-bit A)
|
||||||
- bitmap font:`uint8_t` 1-bit mask(8 个像素打包为 1 个字节)
|
- bitmap font:`uint8_t` 1-bit mask(8 个像素打包为 1 个字节)
|
||||||
|
|
||||||
sprite 相关像素格式约定为:
|
sprite 运行时像素格式统一为 `RGBA5551`(16-bit),内部 backbuffer 统一为 `RGB565`;透明仅支持 1-bit alpha test(`A=0` 跳过,`A=1` 覆写)。
|
||||||
|
|
||||||
```text
|
|
||||||
(R << 24) | (G << 16) | (B << 8) | A
|
|
||||||
```
|
|
||||||
|
|
||||||
当前转换工具位于 `tools/`,需要 Python 和 Pillow:
|
当前转换工具位于 `tools/`,需要 Python 和 Pillow:
|
||||||
|
|
||||||
|
|
@ -195,10 +191,10 @@ python tools/png_to_header.py assets/sprite/test_sprite.png assets/sprite/test_s
|
||||||
```cpp
|
```cpp
|
||||||
test_sprite_width
|
test_sprite_width
|
||||||
test_sprite_height
|
test_sprite_height
|
||||||
test_sprite_pixels
|
test_sprite_pixels // uint16_t RGBA5551 数组
|
||||||
```
|
```
|
||||||
|
|
||||||
透明像素仍保留 alpha;当前 demo 通过 `RenderData::Image(..., 0x00000000)` 把全透明像素作为 color key 跳过。
|
透明像素转换为 RGBA5551 后,alpha 仅 1-bit(`A=0` 透明,`A=1` 不透明)。当前 demo 通过 `RenderData::Image` 的 color_key 机制跳过指定颜色值。
|
||||||
|
|
||||||
Tom 游戏资源使用 `SpriteAssetTool` 从固定目录 `src/Apps/Game/assets/raw/` 读取原始 PNG,一步生成 atlas 头文件。主机侧构建 `IMX6U-Game` 时 CMake 会自动执行 `GenerateTomAtlasHeader`;也可以单独执行:
|
Tom 游戏资源使用 `SpriteAssetTool` 从固定目录 `src/Apps/Game/assets/raw/` 读取原始 PNG,一步生成 atlas 头文件。主机侧构建 `IMX6U-Game` 时 CMake 会自动执行 `GenerateTomAtlasHeader`;也可以单独执行:
|
||||||
|
|
||||||
|
|
@ -214,7 +210,7 @@ src/Apps/Game/generated/tom_atlas.h
|
||||||
|
|
||||||
该头文件包含 `tom_atlas_pixels` 和每张图的 `RenderData::Sprite`,因此板端运行 Tom 游戏时不需要额外部署图片资源文件。尺寸规则、region 名称和 PNG 文件名统一记录在 `src/Apps/Game/tools/asset_pipeline/SpriteAssetTool.cpp` 顶部的 `Sources` 表里;CMake 不再重复维护每张 PNG 的路径。
|
该头文件包含 `tom_atlas_pixels` 和每张图的 `RenderData::Sprite`,因此板端运行 Tom 游戏时不需要额外部署图片资源文件。尺寸规则、region 名称和 PNG 文件名统一记录在 `src/Apps/Game/tools/asset_pipeline/SpriteAssetTool.cpp` 顶部的 `Sources` 表里;CMake 不再重复维护每张 PNG 的路径。
|
||||||
|
|
||||||
`src/Apps/Game/assets/sprites/` 属于旧的 `.sprite` 文件部署流程,Tom 主游戏现在不再依赖它。只有旧的手动测试或未迁移工具还可能引用该目录;清理这些旧入口后可以删除这个目录。
|
`assets/sprite/` 用于存放测试用 PNG sprite 源文件及转换后的头文件,Tom 主游戏不依赖它。Tom 游戏的 atlas 资源由 `src/Apps/Game/tools/asset_pipeline/SpriteAssetTool.cpp` 从 `src/Apps/Game/assets/raw/` 读取原始 PNG 生成。
|
||||||
|
|
||||||
### Bitmap Font 转换
|
### Bitmap Font 转换
|
||||||
|
|
||||||
|
|
@ -281,20 +277,32 @@ IMX6U-Game/
|
||||||
│ └─ sprite/ # PNG sprite 源文件及转换后的头文件
|
│ └─ sprite/ # PNG sprite 源文件及转换后的头文件
|
||||||
├─ tools/
|
├─ tools/
|
||||||
│ ├─ gen_font_atlas.py # TTF -> bitmap font atlas/header
|
│ ├─ gen_font_atlas.py # TTF -> bitmap font atlas/header
|
||||||
│ └─ png_to_header.py # PNG -> uint32_t RGBA header
|
│ └─ png_to_header.py # PNG -> uint16_t RGBA5551 header
|
||||||
├─ src/
|
├─ src/
|
||||||
│ ├─ Core/ # 底层图形库:可复用、无具体游戏规则
|
│ ├─ Core/ # 底层图形库:可复用、无具体游戏规则
|
||||||
│ │ ├─ Draw2D/ # DrawContext 统一绘制入口
|
│ │ ├─ Draw2D/ # DrawContext 统一绘制入口
|
||||||
│ │ ├─ Core/ # FrameBuffer、DepthBuffer
|
│ │ ├─ Core/ # FrameBuffer、DepthBuffer、Renderer、Timer
|
||||||
│ │ ├─ Math/ # 向量、矩阵、数学工具
|
│ │ ├─ Math/ # 向量、矩阵、数学工具
|
||||||
│ │ ├─ Rasterizer/ # 线段、三角形光栅化
|
│ │ ├─ Rasterizer/ # 线段、三角形光栅化
|
||||||
│ │ ├─ RenderData/ # Color、Triangle 等数据结构
|
│ │ ├─ RenderData/ # Color、Image、Sprite、Tilemap、BitmapFont 等数据结构
|
||||||
│ │ ├─ Scene/ # Camera、Transform、Mesh
|
│ │ ├─ Scene/ # Camera、Transform、Mesh、Model
|
||||||
│ │ ├─ Shading/ # 着色器(预留)
|
│ │ ├─ Shading/ # BlinnPhongShader 等着色器
|
||||||
│ │ ├─ Platform/ # IDisplay、SDLDisplay、FBDisplay、ITimeSource
|
│ │ ├─ Platform/ # IDisplay、SDLDisplay、FBDisplay、ITimeSource
|
||||||
│ │ └─ Asset/ # ObjLoader 等资源加载
|
│ │ │ # IAudioInput/Output、IButtonInput、IPointerInput
|
||||||
|
│ │ │ # ALSA / evdev / SDL2 后端、DefaultHardware
|
||||||
|
│ │ └─ Asset/ # ObjLoader、SpriteAssetLoader
|
||||||
│ ├─ Apps/
|
│ ├─ Apps/
|
||||||
│ │ └─ Demo/ # 当前 3D 立方体 demo 入口
|
│ │ ├─ Demo/ # 2D sprite/tilemap 性能测试入口
|
||||||
|
│ │ └─ Game/ # Tom 游戏
|
||||||
|
│ │ ├─ Main.cpp # 游戏入口
|
||||||
|
│ │ ├─ generated/tom_atlas.h # 自动生成的 atlas 头文件
|
||||||
|
│ │ ├─ tools/asset_pipeline/ # SpriteAssetTool(离线资源转换)
|
||||||
|
│ │ └─ src/
|
||||||
|
│ │ ├─ app/ # TomGameApp
|
||||||
|
│ │ ├─ audio/ # VoiceEffect、VoicePlayer、VoiceRecorder
|
||||||
|
│ │ ├─ components/ # SpriteAnimator
|
||||||
|
│ │ ├─ scenes/ # TomScene
|
||||||
|
│ │ └─ systems/ # AnimationSystem
|
||||||
│ └─ test_fb.cpp # 独立 fb 测试(最小示例)
|
│ └─ test_fb.cpp # 独立 fb 测试(最小示例)
|
||||||
├─ docs/
|
├─ docs/
|
||||||
│ ├─ DEVELOPMENT_GUIDELINES.md # IMX6U 性能红线
|
│ ├─ DEVELOPMENT_GUIDELINES.md # IMX6U 性能红线
|
||||||
|
|
@ -307,13 +315,19 @@ IMX6U-Game/
|
||||||
## 模块说明
|
## 模块说明
|
||||||
|
|
||||||
### Draw2D
|
### Draw2D
|
||||||
- **DrawContext**:统一绘制入口,封装 FrameBuffer、DepthBuffer、Rasterizer、TriangleRasterizer,对外提供 `clear`、`draw_line`、`draw_triangle`、`draw_sprite`、`draw_text`、`draw_tilemap`、`present` 接口
|
- **DrawContext**:统一绘制入口,封装 FrameBuffer、DepthBuffer、Rasterizer、TriangleRasterizer,对外提供 `clear`、`clear_color`、`clear_depth`、`draw_line`、`draw_triangle`、`draw_sprite`、`draw_sprite_ex`、`draw_text`、`draw_tilemap`、`fill_rect`、`present` 接口
|
||||||
- **Sprite**:描述 atlas 中的子区域,是对外 sprite 绘制单位;`draw_sprite` / `draw_sprite_ex` 读取其 atlas 子区域并写入 RGB565 framebuffer
|
|
||||||
- **Tilemap**:使用 `uint16_t` tile id 引用 atlas 中的固定大小 tile,`draw_tilemap` 按视口可见范围遍历 tile,并在视口边缘做像素级裁剪
|
### RenderData
|
||||||
|
- **Image**:通用图像数据结构,持有 `const void* pixels` 和 `PixelFormat`(当前统一 `RGBA5551`),支持 color_key 透明跳过
|
||||||
|
- **Sprite**:描述 atlas 中的子区域,通过 `const Image* atlas` 引用源图,是对外 sprite 绘制单位
|
||||||
|
- **Tilemap**:使用 `uint16_t` tile id 引用 atlas 中的固定大小 tile,`EmptyTile` (`0xFFFF`) 表示空 tile
|
||||||
|
- **BitmapFont**:bitmap 字体数据,持有 `uint8_t* mask_bits`(row-major、MSB-first 1-bit mask),支持 ASCII 范围字符绘制
|
||||||
|
- **Color**:RGBA8888 颜色值,用于绘制接口参数和调试;sprite 运行时像素格式仍为 RGBA5551
|
||||||
|
|
||||||
### Core
|
### Core
|
||||||
- **FrameBuffer**:CPU 侧颜色缓冲,渲染结果先写在这里
|
- **FrameBuffer**:CPU 侧 RGB565 颜色缓冲,渲染结果先写在这里
|
||||||
- **DepthBuffer**:深度测试用 Z-buffer
|
- **DepthBuffer**:深度测试用 Z-buffer
|
||||||
|
- **Renderer**:渲染器辅助工具
|
||||||
- **Timer**:整数毫秒固定步长 tick 生成器,支持 30/45/60 FPS 档位和每帧剩余时间计算
|
- **Timer**:整数毫秒固定步长 tick 生成器,支持 30/45/60 FPS 档位和每帧剩余时间计算
|
||||||
|
|
||||||
### Math
|
### Math
|
||||||
|
|
@ -321,14 +335,18 @@ IMX6U-Game/
|
||||||
- 纯头文件实现,无动态分配
|
- 纯头文件实现,无动态分配
|
||||||
|
|
||||||
### Rasterizer
|
### Rasterizer
|
||||||
- **Rasterizer**:Bresenham 线段光栅化
|
- **Rasterizer**:Bresenham 线段光栅化,入口做快速全屏可见性检查,屏幕内走 `set_pixel_unsafe` 快路径,屏幕外走 Cohen-Sutherland 裁剪
|
||||||
- **TriangleRasterizer**:扫描线三角形填充 + 深度测试
|
- **TriangleRasterizer**:扫描线三角形填充 + 定点深度插值(增量式整数边缘函数,内层循环无 float 运算)
|
||||||
|
|
||||||
### Platform
|
### Platform
|
||||||
- **IDisplay**:显示后端抽象,解耦渲染与输出
|
- **IDisplay**:显示后端抽象,解耦渲染与输出
|
||||||
- **SDLDisplay**:SDL2 后端,PC 调试和 IMX6U SDL2 目标路径共用这一类适配思想
|
- **SDLDisplay**:SDL2 后端,PC 调试和 IMX6U SDL2 目标路径共用这一类适配思想
|
||||||
- **FBDisplay**:`/dev/fb0` 对照后端,用于极简显示通路验证
|
- **FBDisplay**:`/dev/fb0` 对照后端,用于极简显示通路验证
|
||||||
- **ITimeSource / SteadyTimeSource**:独立时间源接口与单调时钟实现;Linux/IMX6U 使用 `clock_gettime(CLOCK_MONOTONIC)`,Windows 使用 `std::chrono::steady_clock`,Display 不再承担计时职责
|
- **ITimeSource / SteadyTimeSource**:独立时间源接口与单调时钟实现;Linux/IMX6U 使用 `clock_gettime(CLOCK_MONOTONIC)`,Windows 使用 `std::chrono::steady_clock`,Display 不再承担计时职责
|
||||||
|
- **IAudioInput / IAudioOutput**:音频输入/输出抽象接口,SDL2 和 ALSA 两套后端
|
||||||
|
- **IButtonInput**:按键输入抽象接口,SDL2 键盘和 Linux evdev 两套后端
|
||||||
|
- **IPointerInput**:触摸/指针输入抽象接口,SDL2 和 Linux evdev 两套后端
|
||||||
|
- **DefaultHardware**:根据编译配置自动选择默认音频、按键、指针后端的 typedef
|
||||||
|
|
||||||
### Framebuffer 性能说明
|
### Framebuffer 性能说明
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,14 @@ src/
|
||||||
Apps/
|
Apps/
|
||||||
Demo/ # 2D sprite/tilemap 性能测试入口
|
Demo/ # 2D sprite/tilemap 性能测试入口
|
||||||
Game/ # Tom 游戏
|
Game/ # Tom 游戏
|
||||||
|
generated/ # 自动生成的 tom_atlas.h
|
||||||
|
tools/ # SpriteAssetTool(离线资源转换)
|
||||||
|
src/
|
||||||
|
app/ # TomGameApp
|
||||||
|
audio/ # VoiceEffect、VoicePlayer、VoiceRecorder
|
||||||
|
components/ # SpriteAnimator
|
||||||
|
scenes/ # TomScene
|
||||||
|
systems/ # AnimationSystem
|
||||||
```
|
```
|
||||||
|
|
||||||
`src/Core/Core` 这个二级目录保留的是原底层库里的核心运行时对象。它和顶层 `src/Core` 名称重复,但含义不同:
|
`src/Core/Core` 这个二级目录保留的是原底层库里的核心运行时对象。它和顶层 `src/Core` 名称重复,但含义不同:
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
|
|
||||||
当前项目已经接入 `Core::DepthBuffer`,并采用以下规则:
|
当前项目已经接入 `Core::DepthBuffer`,并采用以下规则:
|
||||||
|
|
||||||
- `DepthBuffer` 存储类型为 `float`
|
- `DepthBuffer` 存储类型为 `float`;`TriangleRasterizer` 内部使用定点深度插值(`depth_fp += depth_fp_per_pixel`,提取时 `>> 16`),内层循环无 float 运算
|
||||||
- 每帧开始时必须调用 `depthBuffer->clear()`,默认清为 `INFINITY`
|
- 每帧开始时必须调用 `depthBuffer->clear()`,默认清为 `INFINITY`
|
||||||
- 当前约定为“深度值越小,离相机越近”
|
- 当前约定为“深度值越小,离相机越近”
|
||||||
- 深度测试通过后,必须同时更新 `DepthBuffer` 和 `FrameBuffer`
|
- 深度测试通过后,必须同时更新 `DepthBuffer` 和 `FrameBuffer`
|
||||||
|
|
@ -133,17 +133,14 @@
|
||||||
|
|
||||||
当前三角形光栅化里的深度流程为:
|
当前三角形光栅化里的深度流程为:
|
||||||
|
|
||||||
- 在屏幕空间遍历三角形包围盒
|
- 使用增量式整数边缘函数替代每像素 float 重心计算和除法
|
||||||
- 以像素中心 `x + 0.5, y + 0.5` 作为采样点
|
- 深度插值使用定点算术:`depth_fp += depth_fp_per_pixel`,提取时 `>> 16`
|
||||||
- 用屏幕空间 `x/y` 计算重心坐标
|
|
||||||
- 用同一组重心坐标判断点是否在三角形内,并插值顶点 `z`
|
|
||||||
- 若新深度更近,则写入 `DepthBuffer` 和 `FrameBuffer`
|
- 若新深度更近,则写入 `DepthBuffer` 和 `FrameBuffer`
|
||||||
|
|
||||||
也就是说:
|
也就是说:
|
||||||
|
|
||||||
- 重心坐标的计算是二维问题,只使用屏幕空间 `x/y`
|
- 当前实现已定点化,内层循环无 float 运算,符合 `DEVELOPMENT_GUIDELINES.md` 性能红线
|
||||||
- 顶点 `z` 的插值使用这组重心权重完成
|
- 后续如果引入纹理、法线或更严格的属性插值,需要进一步考虑透视校正插值
|
||||||
- 当前实现是屏幕空间线性插值,后续如果引入纹理、法线或更严格的属性插值,需要进一步考虑透视校正插值
|
|
||||||
|
|
||||||
## 10. Demo 中的可见性规则
|
## 10. Demo 中的可见性规则
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue