引入 Gfx::DrawContext 统一绘制入口,封装FrameBuffer/DepthBuffer/Rasterizer/角形光栅化;main.cpp 改用 DrawContext;同步更新文档路径
This commit is contained in:
parent
a051f6da4c
commit
3e735e27b0
|
|
@ -12,6 +12,7 @@ set(SOURCES
|
|||
src/Gfx/Core/DepthBuffer.cpp
|
||||
src/Gfx/Core/FrameBuffer.cpp
|
||||
src/Gfx/Core/Renderer.cpp
|
||||
src/Gfx/Draw2D/DrawContext.cpp
|
||||
src/Gfx/Rasterizer/Rasterizer.cpp
|
||||
src/Gfx/Rasterizer/TriangleRasterizer.cpp
|
||||
src/Gfx/Scene/Camera.cpp
|
||||
|
|
@ -30,6 +31,7 @@ target_include_directories(IMX6U-Game PRIVATE
|
|||
src/Gfx/Platform
|
||||
src/Gfx/Asset
|
||||
src/Gfx/Core
|
||||
src/Gfx/Draw2D
|
||||
src/Gfx/Math
|
||||
src/Gfx/Rasterizer
|
||||
src/Gfx/RenderData
|
||||
|
|
|
|||
37
README.md
37
README.md
|
|
@ -57,7 +57,7 @@ cd IMX6U-Game
|
|||
仓库已自带 SDL2 开发库(`libs/Win/SDL2`),无需额外安装。
|
||||
|
||||
```bash
|
||||
cmake -B build-win .
|
||||
cmake -B build-win .m
|
||||
cmake --build build-win --config Release
|
||||
```
|
||||
|
||||
|
|
@ -150,8 +150,6 @@ Framebuffer 对照版本可能需要 root 权限访问 `/dev/fb0`。SDL2 版本
|
|||
|
||||
## 目录结构
|
||||
|
||||
当前源码仍处于早期验证布局:
|
||||
|
||||
```text
|
||||
IMX6U-Game/
|
||||
├─ cmake/
|
||||
|
|
@ -161,27 +159,32 @@ IMX6U-Game/
|
|||
│ ├─ 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 主循环
|
||||
│ ├─ Gfx/ # 底层图形库:可复用、无具体游戏规则
|
||||
│ │ ├─ Draw2D/ # DrawContext 统一绘制入口
|
||||
│ │ ├─ Core/ # FrameBuffer、DepthBuffer
|
||||
│ │ ├─ Math/ # 向量、矩阵、数学工具
|
||||
│ │ ├─ Rasterizer/ # 线段、三角形光栅化
|
||||
│ │ ├─ RenderData/ # Color、Triangle 等数据结构
|
||||
│ │ ├─ Scene/ # Camera、Transform、Mesh
|
||||
│ │ ├─ Shading/ # 着色器(预留)
|
||||
│ │ ├─ Platform/ # IDisplay、SDLDisplay、FBDisplay
|
||||
│ │ └─ Asset/ # ObjLoader 等资源加载
|
||||
│ ├─ Apps/
|
||||
│ │ └─ Demo/ # 当前 3D 立方体 demo 入口
|
||||
│ └─ test_fb.cpp # 独立 fb 测试(最小示例)
|
||||
├─ docs/
|
||||
│ ├─ DEVELOPMENT_GUIDELINES.md # IMX6U 性能红线
|
||||
│ └─ APP_AND_GFX_ARCHITECTURE.md # 应用层与图形库分层
|
||||
│ ├─ APP_AND_GFX_ARCHITECTURE.md # 应用层与图形库分层
|
||||
│ └─ CONVENTIONS.md # 坐标系、矩阵、深度等数学约定
|
||||
├─ CMakeLists.txt
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
目标布局见 `docs/APP_AND_GFX_ARCHITECTURE.md`:后续会收敛为 `src/Gfx`、`src/Apps/Launcher`、`src/Apps/GameA`、`src/Apps/GameB`、`src/Shared`。
|
||||
|
||||
## 模块说明
|
||||
|
||||
### Draw2D
|
||||
- **DrawContext**:统一绘制入口,封装 FrameBuffer、DepthBuffer、Rasterizer、TriangleRasterizer,对外提供 `clear`、`draw_line`、`draw_triangle`、`present` 接口
|
||||
|
||||
### Core
|
||||
- **FrameBuffer**:CPU 侧颜色缓冲,渲染结果先写在这里
|
||||
- **DepthBuffer**:深度测试用 Z-buffer
|
||||
|
|
@ -204,6 +207,8 @@ IMX6U-Game/
|
|||
**已完成:**
|
||||
- 可旋转立方体的 3D 渲染(MVP 变换、背面剔除、扫描线填充、深度测试)
|
||||
- 双平台显示后端(SDL2 / Framebuffer)
|
||||
- Gfx 目录规范化,代码收敛到 `src/Gfx/`
|
||||
- `Gfx::DrawContext` 统一绘制入口,封装现有绘制能力
|
||||
- C++11 兼容代码
|
||||
- CMake 跨平台构建
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,20 @@
|
|||
IMX6U-Game/
|
||||
├─ src/
|
||||
│ ├─ Gfx/ # 底层图形库:可复用、无具体游戏规则
|
||||
│ │ ├─ Core/ # FrameBuffer、DepthBuffer、RendererContext
|
||||
│ │ ├─ Draw2D/ # rect、quad、line、sprite、tile 等基础绘制
|
||||
│ │ ├─ Math/ # 定点数、向量、矩阵、几何工具
|
||||
│ │ ├─ RenderData/ # Color、Rect、Quad、Texture、Vertex 等数据结构
|
||||
│ │ └─ Platform/ # SDL2 / fb0 / input / timer 的平台适配
|
||||
│ │ ├─ Draw2D/ # DrawContext 统一绘制入口(✅ 已实现)
|
||||
│ │ ├─ Core/ # FrameBuffer、DepthBuffer(✅ 已实现)
|
||||
│ │ ├─ Math/ # 向量、矩阵、数学工具(✅ 已实现)
|
||||
│ │ ├─ Rasterizer/ # 线段、三角形光栅化(✅ 已实现)
|
||||
│ │ ├─ RenderData/ # Color、Triangle 等数据结构(✅ 已实现)
|
||||
│ │ ├─ Scene/ # Camera、Transform(✅ 已实现)
|
||||
│ │ ├─ Shading/ # 着色器(预留)
|
||||
│ │ ├─ Platform/ # SDL2 / fb0 平台适配(✅ 已实现)
|
||||
│ │ └─ Asset/ # 资源加载(✅ 已实现)
|
||||
│ ├─ Apps/
|
||||
│ │ ├─ Launcher/ # 启动器应用
|
||||
│ │ ├─ GameA/ # 第一个游戏
|
||||
│ │ └─ GameB/ # 第二个游戏
|
||||
│ │ ├─ Demo/ # 当前 3D 立方体 demo(✅ 已实现)
|
||||
│ │ ├─ Launcher/ # 启动器应用(待实现)
|
||||
│ │ ├─ GameA/ # 第一个游戏(待实现)
|
||||
│ │ └─ GameB/ # 第二个游戏(待实现)
|
||||
│ └─ Shared/ # 可选:应用层共享但不属于 Gfx 的东西
|
||||
│ ├─ Save/ # 存档格式、配置读写
|
||||
│ ├─ UI/ # 启动器和游戏共用 UI 组件
|
||||
|
|
@ -31,7 +36,9 @@ IMX6U-Game/
|
|||
└─ docs/
|
||||
```
|
||||
|
||||
当前项目已有 `Core/Math/Platform/Rasterizer/RenderData/Scene` 等目录,短期不必一次性搬迁;但新增代码应按上面的边界收敛。等功能稳定后,再把现有底层代码整体移动到 `src/Gfx/`。
|
||||
~~当前项目已有 `Core/Math/Platform/Rasterizer/RenderData/Scene` 等目录,短期不必一次性搬迁;但新增代码应按上面的边界收敛。等功能稳定后,再把现有底层代码整体移动到 `src/Gfx/`。~~
|
||||
|
||||
**已完成**:底层代码已整体迁移到 `src/Gfx/`,包括 Core、Math、Rasterizer、RenderData、Scene、Shading、Platform、Asset 和新增的 Draw2D。Demo 入口位于 `src/Apps/Demo/`。
|
||||
|
||||
## 2. 四个层级的职责
|
||||
|
||||
|
|
@ -201,13 +208,14 @@ namespace Gfx
|
|||
|
||||
## 7. 推荐演进顺序
|
||||
|
||||
1. 先抽出统一 `IApp` 和 `AppManager`,让当前 demo 成为一个 app。
|
||||
2. 把 SDL2 初始化、输入、present 固定在平台层,应用层不直接碰 SDL。
|
||||
3. 建立 `Gfx::DrawContext`,先封装 clear、pixel、line、rect、quad。
|
||||
4. 新增 Launcher app,只做最小菜单和应用切换。
|
||||
5. 新增 GameA/GameB 空壳,验证三应用切换。
|
||||
6. 再逐步把现有 3D demo 或 2D 游戏逻辑迁入对应 Game 目录。
|
||||
7. 最后重构 CMake,按 `imx6u_gfx` + 应用 target 拆分。
|
||||
1. ~~先抽出统一 `IApp` 和 `AppManager`,让当前 demo 成为一个 app。~~
|
||||
2. ~~把 SDL2 初始化、输入、present 固定在平台层,应用层不直接碰 SDL。~~
|
||||
3. ~~建立 `Gfx::DrawContext`,先封装 clear、pixel、line、rect、quad。~~ **已完成**(`Gfx::DrawContext` 封装了 clear、draw_line、draw_triangle、present)
|
||||
4. ~~底层代码迁移到 `src/Gfx/`,Demo 入口迁移到 `src/Apps/Demo/`。~~ **已完成**
|
||||
5. 新增 Launcher app,只做最小菜单和应用切换。
|
||||
6. 新增 GameA/GameB 空壳,验证三应用切换。
|
||||
7. 再逐步把现有 3D demo 或 2D 游戏逻辑迁入对应 Game 目录。
|
||||
8. 最后重构 CMake,按 `imx6u_gfx` + 应用 target 拆分。
|
||||
|
||||
## 8. 性能注意事项
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
- **先按 IMX6U 运行时成本设计,再按 PC 调试便利包装。** Windows/Linux SDL 版本只是验证与调试入口,不代表最终性能预算。
|
||||
- **热路径默认禁止隐式高成本操作。** 每帧、每对象、每顶点、每像素级代码必须避免动态分配、浮点、虚函数链、复杂 STL 算法和异常控制流。
|
||||
- **核心逻辑保持 C++11 兼容。** 不引入需要新工具链或重型运行时支持的语言/库特性。
|
||||
- **优先复用已有类型与缓冲。** 新增抽象前先确认 `src/Core`、`src/Math`、`src/RenderData` 中是否已有可复用能力。
|
||||
- **优先复用已有类型与缓冲。** 新增抽象前先确认 `src/Gfx/Core`、`src/Gfx/Math`、`src/Gfx/RenderData` 中是否已有可复用能力。
|
||||
- **性能相关例外必须写明边界。** 如果必须违反本文红线,需要在代码附近注释说明原因、调用频率、数据规模和替代方案。
|
||||
|
||||
## 2. 数值计算规范
|
||||
|
|
@ -124,13 +124,13 @@
|
|||
- [ ] 是否把平台/显示层 API 类型泄漏进核心逻辑?
|
||||
- [ ] 是否能在 PC 调试版和 ARM release 版分别关闭调试开销?
|
||||
- [ ] 是否保留 C++11 兼容?
|
||||
- [ ] 是否需要同步更新 `src/CONVENTIONS.md` 中的坐标/矩阵/深度等约定?
|
||||
- [ ] 是否需要同步更新 `docs/CONVENTIONS.md` 中的坐标/矩阵/深度等约定?
|
||||
|
||||
## 9. 推荐的代码结构方向
|
||||
|
||||
后续如果继续推进性能优化,优先建立这些基础设施:
|
||||
|
||||
1. 统一定点数类型与转换工具,集中放在 `src/Math/`。
|
||||
1. 统一定点数类型与转换工具,集中放在 `src/Gfx/Math/`。
|
||||
2. 帧级临时缓冲/工作区,集中管理可复用数组和 scratch memory。
|
||||
3. 渲染数据的运行时紧凑格式,区分“加载期模型数据”和“运行时渲染数据”。
|
||||
4. ARM release 配置下的性能开关,关闭日志、调试绘制和昂贵检查。
|
||||
|
|
@ -150,8 +150,8 @@
|
|||
|
||||
### 11.1 SDL2 边界
|
||||
|
||||
- SDL2 类型和调用只允许出现在 `src/Platform/` 以及明确的平台适配层中。
|
||||
- `src/Core`、`src/Math`、`src/Rasterizer`、`src/RenderData`、`src/Scene` 不应直接包含 `SDL.h`。
|
||||
- SDL2 类型和调用只允许出现在 `src/Gfx/Platform/` 以及明确的平台适配层中。
|
||||
- `src/Gfx/Core`、`src/Gfx/Math`、`src/Gfx/Rasterizer`、`src/Gfx/RenderData`、`src/Gfx/Scene`、`src/Gfx/Draw2D` 不应直接包含 `SDL.h`。
|
||||
- 游戏逻辑不直接处理 `SDL_Event`,应转换为项目自己的输入状态结构。
|
||||
- 时间源可以来自 SDL,但核心逻辑使用整数 tick / fixed timestep,不直接依赖 float 秒数。
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,11 @@
|
|||
#include "Matrix4x4.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Color.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "TriangleRasterizer.h"
|
||||
#include "Triangle.h"
|
||||
#include "Camera.h"
|
||||
#include <cstdlib>
|
||||
#include "Vertex.h"
|
||||
#include "DepthBuffer.h"
|
||||
#include "DrawContext.h"
|
||||
|
||||
#include "Display.h"
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
|
|
@ -117,10 +114,7 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
Core::FrameBuffer *frameBuffer = new Core::FrameBuffer(width, height);
|
||||
Core::DepthBuffer *depthBuffer = new Core::DepthBuffer(width, height);
|
||||
Rasterizer::Rasterizer rasterizer(frameBuffer, depthBuffer);
|
||||
Rasterizer::TriangleRasterizer triangleRasterizer(frameBuffer, depthBuffer);
|
||||
Gfx::DrawContext ctx(width, height);
|
||||
|
||||
Scene::Camera camera;
|
||||
camera.transform.position = Math::Vector3(0.0f, 0.0f, 3.0f);
|
||||
|
|
@ -155,13 +149,12 @@ int main(int argc, char *argv[])
|
|||
const RenderData::Color cubeColor(240, 240, 240, 255);
|
||||
const float aspectRatio = static_cast<float>(width) / static_cast<float>(height);
|
||||
|
||||
bool isRuning = true;
|
||||
while (isRuning)
|
||||
bool isRunning = true;
|
||||
while (isRunning)
|
||||
{
|
||||
display->poll_events(isRuning);
|
||||
display->poll_events(isRunning);
|
||||
|
||||
frameBuffer->clear(clearColor);
|
||||
depthBuffer->clear();
|
||||
ctx.clear(clearColor);
|
||||
|
||||
const float timeSeconds = static_cast<float>(display->get_time_ms()) * 0.001f;
|
||||
const Math::Matrix4x4 model =
|
||||
|
|
@ -204,10 +197,6 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
const Math::Vector3 &viewV0 = viewSpaceVertices[cubeTriangle.vertices[0]];
|
||||
const Math::Vector3 &viewV1 = viewSpaceVertices[cubeTriangle.vertices[1]];
|
||||
const Math::Vector3 &viewV2 = viewSpaceVertices[cubeTriangle.vertices[2]];
|
||||
|
||||
drawTriangles[drawCommandCount++] =
|
||||
RenderData::Triangle(
|
||||
Scene::Vertex(v0.screen),
|
||||
|
|
@ -217,7 +206,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
for (size_t i = 0; i < drawCommandCount; ++i)
|
||||
{
|
||||
triangleRasterizer.DrawTriangle2D(drawTriangles[i], cubeColor);
|
||||
ctx.draw_triangle(drawTriangles[i], cubeColor);
|
||||
}
|
||||
|
||||
for (size_t faceIndex = 0; faceIndex < cubeFaces.size(); ++faceIndex)
|
||||
|
|
@ -239,19 +228,17 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
rasterizer.DrawLine(
|
||||
ctx.draw_line(
|
||||
Math::Vector2(start.screen.x, start.screen.y).to_vector2Int(),
|
||||
Math::Vector2(end.screen.x, end.screen.y).to_vector2Int(),
|
||||
clearColor);
|
||||
}
|
||||
}
|
||||
|
||||
display->present(frameBuffer);
|
||||
ctx.present(display);
|
||||
}
|
||||
|
||||
display->shutdown();
|
||||
delete display;
|
||||
delete frameBuffer;
|
||||
delete depthBuffer;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
#include "DrawContext.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "DepthBuffer.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "TriangleRasterizer.h"
|
||||
#include "Display.h"
|
||||
|
||||
namespace Gfx
|
||||
{
|
||||
DrawContext::DrawContext(int32_t width, int32_t height)
|
||||
{
|
||||
frameBuffer = new Core::FrameBuffer(width, height);
|
||||
depthBuffer = new Core::DepthBuffer(width, height);
|
||||
rasterizer = new Rasterizer::Rasterizer(frameBuffer, depthBuffer);
|
||||
triangleRasterizer = new Rasterizer::TriangleRasterizer(frameBuffer, depthBuffer);
|
||||
}
|
||||
|
||||
DrawContext::~DrawContext()
|
||||
{
|
||||
delete triangleRasterizer;
|
||||
delete rasterizer;
|
||||
delete depthBuffer;
|
||||
delete frameBuffer;
|
||||
}
|
||||
|
||||
int32_t DrawContext::get_width() const
|
||||
{
|
||||
return frameBuffer->get_width();
|
||||
}
|
||||
|
||||
int32_t DrawContext::get_height() const
|
||||
{
|
||||
return frameBuffer->get_height();
|
||||
}
|
||||
|
||||
void DrawContext::clear(const RenderData::Color& color)
|
||||
{
|
||||
frameBuffer->clear(color);
|
||||
depthBuffer->clear();
|
||||
}
|
||||
|
||||
void DrawContext::clear_depth()
|
||||
{
|
||||
depthBuffer->clear();
|
||||
}
|
||||
|
||||
void DrawContext::draw_line(const Math::Vector2Int& from, const Math::Vector2Int& to, const RenderData::Color& color)
|
||||
{
|
||||
rasterizer->DrawLine(from, to, color);
|
||||
}
|
||||
|
||||
void DrawContext::draw_triangle(const RenderData::Triangle& triangle, const RenderData::Color& color)
|
||||
{
|
||||
triangleRasterizer->DrawTriangle2D(triangle, color);
|
||||
}
|
||||
|
||||
void DrawContext::present(Platform::IDisplay* display)
|
||||
{
|
||||
display->present(frameBuffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
#include "Color.h"
|
||||
#include "Vector2.h"
|
||||
#include "Triangle.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class FrameBuffer;
|
||||
class DepthBuffer;
|
||||
}
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
class Rasterizer;
|
||||
class TriangleRasterizer;
|
||||
}
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
class IDisplay;
|
||||
}
|
||||
|
||||
namespace Gfx
|
||||
{
|
||||
class DrawContext
|
||||
{
|
||||
private:
|
||||
Core::FrameBuffer* frameBuffer;
|
||||
Core::DepthBuffer* depthBuffer;
|
||||
Rasterizer::Rasterizer* rasterizer;
|
||||
Rasterizer::TriangleRasterizer* triangleRasterizer;
|
||||
|
||||
public:
|
||||
DrawContext(int32_t width, int32_t height);
|
||||
~DrawContext();
|
||||
|
||||
DrawContext(const DrawContext&) = delete;
|
||||
DrawContext& operator=(const DrawContext&) = delete;
|
||||
|
||||
int32_t get_width() const;
|
||||
int32_t get_height() const;
|
||||
|
||||
void clear(const RenderData::Color& color);
|
||||
void clear_depth();
|
||||
|
||||
void draw_line(const Math::Vector2Int& from, const Math::Vector2Int& to, const RenderData::Color& color);
|
||||
void draw_triangle(const RenderData::Triangle& triangle, const RenderData::Color& color);
|
||||
|
||||
void present(Platform::IDisplay* display);
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue