Frostbite2D/Engine_Architecture.md

568 lines
40 KiB
Markdown

# Frostbite2D 引擎架构说明
## 1. 整体架构图
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 用户应用层 (main.cpp) │
│ 创建配置 → 初始化应用 → 游戏循环 → 清理 │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 应用程序层 (Application) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 单例管理 │ │ 模块系统 │ │ 时间管理 │ │ 窗口管理 │ │
│ │ get() │ │ use/init │ │ deltaTime() │ │ Window │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ mainLoop() ────────► update()/render() │
└─────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────┼────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ 渲染系统 │ │ 着色器系统 │ │ 输入系统 │
│ (GLRenderer) │◄────►│ (ShaderManager) │ │ (SDL Events) │
└─────────────────┘ └─────────────────────┘ └─────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 渲染核心层 │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ ┌───────────┐ │
│ │ 2D图形绘制 │ │ 精灵批处理 │ │ 字体渲染 │ │ 相机 │ │
│ │ drawRect() │ │ GLSpriteBatch │ │ GLFontAtlas │ │ Camera │ │
│ │ fillCircle() │ │ 10000 sprites │ │ stb_truetype │ │ view/proj │ │
│ │ drawLine() │ │ drawSprite() │ │ cache glyphs │ │ move/zoom │ │
│ │ drawText() │ │ endBatch() │ │ measureText() │ │ │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ └───────────┘ │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ 纹理管理 │ │ 着色器实现 │ │ OpenGL资源 │ │
│ │ GLTexture │ │ GLShader │ │ VAO/VBO │ │
│ │ load from file│ │ vertex/frag │ │ shape/line │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 平台抽象层 │
│ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ │
│ │ Window 窗口 │ │ SDL2 跨平台库 │ │
│ │ - 创建/销毁窗口 │ │ 窗口管理 | 事件处理 | OpenGL上下文 │ │
│ │ - OpenGL 上下文 │ │ │ │
│ │ - 事件轮询 │ │ 支持: Windows | Linux | macOS │ │
│ │ - 交换缓冲区 │ │ Android | iOS | Switch │ │
│ └─────────────────────────┘ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 第三方库 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ OpenGL │ │ SDL2 │ │ GLAD │ │ GLM │ │ stb_truetype │ │
│ │ ES 3.2 │ │ 2.32.2 │ │ Loader │ │ 1.0.3 │ │ rect_pack │ │
│ │ 图形API │ │ 窗口/输入 │ │ 函数加载 │ │ 数学库 │ │ 字体渲染 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## 2. 模块详细说明
### 2.1 应用程序层 (Application)
```
┌─────────────────────────────────────────┐
│ Application 单例 │
├─────────────────────────────────────────┤
│ + get() : Application& │
│ + init(config) : bool │
│ + run() : void │
│ + quit() : void │
│ + deltaTime() : float │
│ + fps() : int │
├─────────────────────────────────────────┤
│ - window_ : Window* │
│ - modules_ : vector<Module*> │
│ - running_ : bool │
│ - deltaTime_ : float │
│ - currentFps_ : int │
└─────────────────────────────────────────┘
```
**生命周期流程:**
```
main()
├─► AppConfig config = AppConfig::createDefault()
├─► Application::get().init(config)
│ ├─► 创建 Window
│ ├─► 初始化 SDL
│ └─► 初始化 GLAD (OpenGL 函数加载)
├─► ShaderManager::getInstance().init(factory)
│ ├─► 加载 sprite shader
│ └─► 加载 shape shader
├─► GLRenderer.init(window)
│ ├─► 创建 VAO/VBO
│ ├─► 初始化 SpriteBatch
│ └─► 设置 OpenGL 状态
├─► 游戏主循环
│ ├─► 处理输入事件 (SDL_PollEvent)
│ ├─► renderer.beginFrame(color) // 清除缓冲区
│ ├─► 绘制图形
│ │ ├─► fillRect() 填充矩形
│ │ ├─► fillCircle() 填充圆形
│ │ ├─► drawLine() 绘制线条
│ │ ├─► drawText() 绘制文字
│ │ └─► ...
│ ├─► renderer.endFrame() // 提交批次
│ └─► SDL_GL_SwapWindow() // 显示到屏幕
├─► 清理资源
│ ├─► renderer.shutdown()
│ ├─► ShaderManager::shutdown()
│ └─► Application::shutdown()
└─► return 0
```
### 2.2 渲染系统 (GLRenderer)
**核心功能:**
| 功能类别 | 方法 | 说明 |
|---------|------|------|
| **帧管理** | `beginFrame()` / `endFrame()` | 开始/结束渲染帧 |
| **2D形状** | `fillRect()` / `drawRect()` | 填充/描边矩形 |
| **圆形** | `fillCircle()` / `drawCircle()` | 填充/描边圆形 |
| **线条** | `drawLine()` | 绘制线段 |
| **三角形** | `fillTriangle()` / `drawTriangle()` | 填充/描边三角形 |
| **多边形** | `fillPolygon()` / `drawPolygon()` | 填充/描边多边形 |
| **精灵** | `drawSprite()` | 绘制纹理精灵 |
| **文字** | `drawText()` | 渲染文字 |
| **变换** | `pushTransform()` / `popTransform()` | 矩阵变换栈 |
| **视口** | `setViewport()` | 设置渲染区域 |
| **混合** | `setBlendMode()` | 设置混合模式 |
**渲染管线:**
```
┌──────────────┐ ┌────────────────────────────────────────────────┐
│ drawRect() │────►│ │
└──────────────┘ │ 形状批处理缓冲区 │
┌──────────────┐ │ shapeVertexCache_[MAX_SHAPE_VERTICES] │
│ fillCircle() │────►│ │
└──────────────┘ │ 顶点格式: {x, y, r, g, b, a} │
┌──────────────┐ │ │
│fillTriangle()│────►│ 当缓冲区满或模式改变时: flushShapeBatch() │
└──────────────┘ │ │
└────────────────────┬───────────────────────────┘
┌────────────────────────────────────────────────┐
│ 线条批处理缓冲区 │
│ lineVertexCache_[MAX_LINE_VERTICES] │
│ │
│ 绘制模式: GL_LINES (每线条2顶点) │
│ 支持线宽设置 │
└────────────────────┬───────────────────────────┘
┌────────────────────────────────────────────────┐
│ 精灵批处理系统 │
│ GLSpriteBatch (10000精灵) │
│ │
│ 图集纹理 → 顶点数据 → VBO → GPU 批量绘制 │
│ │
│ beginSpriteBatch() → drawSprite() → endBatch()│
└────────────────────┬───────────────────────────┘
┌────────────────────────────────────────────────┐
│ OpenGL 渲染 │
│ │
│ glDrawArrays(GL_TRIANGLES, ...) │
│ glDrawArrays(GL_LINES, ...) │
└────────────────────────────────────────────────┘
```
### 2.3 着色器系统 (ShaderManager)
```
┌─────────────────────────────────────────────────────────────────┐
│ ShaderManager 单例 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌────────────────────────────────────┐ │
│ │ IShader │◄───┤ GLShader (OpenGL实现) │ │
│ │ 接口 │ │ - 编译 vertex/fragment shader │ │
│ │ │ │ - 创建 program │ │
│ │ bind() │ │ - 设置 uniform │ │
│ │ setUniform() │ │ - 绑定/解绑 │ │
│ └──────────────┘ └────────────────────────────────────┘ │
│ ▲ │
│ │ │
│ ┌──────────────┐ ┌────────────────────────────────────┐ │
│ │ IShaderFactory│◄──┤ GLShaderFactory │ │
│ │ 工厂接口 │ │ - createShader() │ │
│ │ │ │ - 创建 OpenGL Shader 实例 │ │
│ └──────────────┘ └────────────────────────────────────┘ │
│ │
│ 管理: unordered_map<string, ShaderInfo> shaders_ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**内置着色器:**
| 着色器 | 文件 | 用途 |
|-------|------|------|
| **sprite** | sprite.vert / sprite.frag | 纹理精灵渲染 (支持颜色混合) |
| **shape** | shape.vert / shape.frag | 2D形状渲染 (顶点颜色) |
### 2.4 字体渲染 (GLFontAtlas)
```
┌─────────────────────────────────────────────────────────────────┐
│ 字体图集系统 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 初始化流程: │
│ ┌───────────┐ ┌───────────┐ ┌──────────────────────┐ │
│ │ 加载字体 │───►│ 初始化stb │───►│ 创建 1024x1024 图集 │ │
│ │ 文件(.ttf)│ │ _truetype │ │ 纹理 (RGBA) │ │
│ └───────────┘ └───────────┘ └──────────────────────┘ │
│ │ │
│ 渲染字符时: │ │
│ ┌───────────┐ ┌───────────┐ ┌────────▼──────────┐ │
│ │ 字符查缓存 │───►│ 缓存未命中 │───►│ stbtt_MakeCodepoint│ │
│ │ │ │ │ │ _Bitmap() 栅格化 │ │
│ └─────┬─────┘ └───────────┘ └────────┬──────────┘ │
│ │ │ │
│ │ ┌───────────┐ ┌─────────▼──────────┐ │
│ └────────►│ 返回字形 │◄───│ stb_rect_pack 打包 │ │
│ │ 信息 │ │ 到图集纹理 │ │
│ └───────────┘ └────────────────────┘ │
│ │
│ Glyph 信息: │
│ - 尺寸 (width, height) │
│ - 偏移 (bearingX, bearingY) │
│ - 步进 (advance) │
│ - 纹理坐标 (u0, v0, u1, v1) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 2.5 相机系统 (Camera)
```
┌─────────────────────────────────────────┐
│ Camera 相机 │
├─────────────────────────────────────────┤
│ │
│ 视口配置: │
│ ┌─────────────────────────────────┐ │
│ │ left = 0 │ │
│ │ right = 800 ─────────────── │ │
│ │ top = 0 │ │ │ │
│ │ bottom = 600 │ 世界坐标 │ │ │
│ │ │ │ │ │
│ │ 默认位置(0,0) │ │ │ │
│ │ 看向左上角 └─────────────┘ │ │
│ │ 视口 (0,0) │ │
│ └─────────────────────────────────┘ │
│ │
│ 变换矩阵: │
│ ┌───────────────┐ │
│ │ viewMatrix │ 视图矩阵 (相机位置) │
│ ├───────────────┤ │
│ │ projMatrix │ 正交投影矩阵 │
│ ├───────────────┤ │
│ │ viewProj │ view * projection │
│ └───────────────┘ │
│ │
│ 控制: │
│ - move(x, y) 移动相机 │
│ - setZoom(z) 设置缩放 │
│ - setPosition() 设置位置 │
│ │
└─────────────────────────────────────────┘
```
### 2.6 模块系统 (Module)
```
┌─────────────────────────────────────────┐
│ Module 模块基类 │
├─────────────────────────────────────────┤
│ + setupModule() 初始化 │
│ + destroyModule() 销毁 │
│ + onUpdate() 每帧更新 │
│ + beforeRender() 渲染前 │
│ + onRender() 渲染时 │
│ + afterRender() 渲染后 │
│ + handleEvent() 事件处理 │
│ + getName() 模块名称 │
│ + getPriority() 优先级 (越小越优先) │
└─────────────────────────────────────────┘
│ 继承
┌──────────────┼──────────────┐
│ │ │
┌───┴───┐ ┌─────┴─────┐ ┌────┴────┐
│渲染模块│ │ 物理模块 │ │音频模块 │
│ │ │ │ │ │
└───────┘ └───────────┘ └─────────┘
```
## 3. 数据流图
### 3.1 一帧的渲染流程
```
┌──────────────────────────────────────────────────────────────────────┐
│ 游戏主循环 │
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ① 处理输入事件 │
│ SDL_PollEvent() → 键盘/鼠标事件 → 更新相机/游戏逻辑 │
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ② 开始新帧 (beginFrame) │
│ glClear() 清除颜色缓冲区 + 重置渲染统计 │
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ③ 设置渲染状态 │
│ setViewport() + setViewProjection(camera.getViewProjectionMatrix)│
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ④ 绘制各种图形 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ fillRect() │ │fillCircle() │ │ drawLine() │ │drawSprite() │ │
│ │ │ │ │ │ │ │ │ │
│ │ 顶点数据 ──►│ │ 顶点数据 ──►│ │ 顶点数据 ──►│ │ 精灵数据 ──►│ │
│ │ 形状缓冲区 │ │ 形状缓冲区 │ │ 线条缓冲区 │ │ 精灵批次 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ⑤ 结束帧 (endFrame) │
│ flushShapeBatch() + flushLineBatch() + endSpriteBatch() │
│ 提交所有待渲染数据到 GPU │
└─────────────────────────────────┬────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ⑥ 交换缓冲区 │
│ SDL_GL_SwapWindow() 将渲染结果显示到屏幕 │
└──────────────────────────────────────────────────────────────────────┘
```
### 3.2 资源加载流程
```
纹理加载:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 文件路径 │───►│ stb_image│───►│ 像素数据 │───►│ GLTexture │
│ .png/.jpg│ │ 解码 │ │ RGBA │ │ glTexImage2D
└──────────┘ └──────────┘ └──────────┘ └──────────┘
字体加载:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ .ttf文件 │───►│读取到内存│───►│stbtt_Init│───►│GLFontAtlas│
│ │ │ │ │Font() │ │ 创建图集 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
着色器加载:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│.vert文件 │───►│读取源码 │───►│glCompile │───►│glLink │
│.frag文件 │───►│ │ │Shader() │ │Program │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
```
## 4. 项目目录结构
```
Frostbite2D/
├── xmake.lua # 主构建配置
├── platform/
│ └── windows.lua # Windows 平台配置
├── shaders/
│ ├── shape.vert # 形状着色器 - 顶点
│ ├── shape.frag # 形状着色器 - 片段
│ ├── sprite.vert # 精灵着色器 - 顶点
│ └── sprite.frag # 精灵着色器 - 片段
└── Fostbite2D/
├── include/
│ ├── fostbite2D/
│ │ ├── app/
│ │ │ └── application.h # 应用主类
│ │ ├── config/
│ │ │ ├── app_config.h # 应用配置
│ │ │ └── platform_config.h # 平台配置
│ │ ├── core/
│ │ │ ├── color.h # 颜色类
│ │ │ ├── math_types.h # 数学类型
│ │ │ └── types.h # 基础类型定义
│ │ ├── module/
│ │ │ └── module.h # 模块基类
│ │ ├── platform/
│ │ │ └── window.h # 窗口类
│ │ └── render/
│ │ ├── camera.h # 相机
│ │ ├── font.h # 字体接口
│ │ ├── texture.h # 纹理接口
│ │ ├── opengl/
│ │ │ ├── gl_font_atlas.h # OpenGL字体图集
│ │ │ ├── gl_renderer.h # OpenGL渲染器
│ │ │ ├── gl_shader.h # OpenGL着色器
│ │ │ ├── gl_sprite_batch.h # 精灵批处理
│ │ │ └── gl_texture.h # OpenGL纹理
│ │ └── shader/
│ │ ├── shader_interface.h # 着色器接口
│ │ └── shader_manager.h # 着色器管理器
│ ├── glad/
│ │ └── glad.h # OpenGL 加载器
│ ├── KHR/
│ │ └── khrplatform.h # Khronos 平台定义
│ └── stb/
│ ├── stb_image.h # 图片加载
│ ├── stb_rect_pack.h # 矩形打包
│ └── stb_truetype.h # 字体渲染
└── src/
├── main.cpp # 程序入口
├── glad/
│ └── glad.c # GLAD 实现
└── fostbite2D/
├── app/
│ └── application.cpp # Application 实现
├── config/
│ └── app_config.cpp # 配置实现
├── platform/
│ └── window.cpp # Window 实现
└── render/
├── camera.cpp # Camera 实现
├── texture.cpp # Texture 实现
├── opengl/ # OpenGL 实现
└── shader/ # Shader 实现
```
## 5. 核心类关系图
```
┌─────────────────┐
│ Application │
│ 单例 │
└────────┬────────┘
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Window │◄───────►│ ShaderManager │◄───────►│ GLRenderer │
│ (SDL2) │ │ 单例 │ │ │
└─────────────────┘ └────────┬────────┘ └───────┬─────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ IShader │ │ GLSpriteBatch │
│ 接口 │ │ 精灵批处理 │
└────────┬────────┘ └───────┬─────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ GLShader │ │ GLTexture │
│ OpenGL实现 │ │ 纹理管理 │
└─────────────────┘ └─────────────────┘
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Camera │◄───────►│ GLFontAtlas │◄───────►│ FontAtlas │
│ 2D相机 │ │ 字体图集 │ │ 接口 │
│ view/proj矩阵 │ │ stb_truetype │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
## 6. 关键技术点
### 6.1 批处理渲染 (Batch Rendering)
- **形状批处理**: 8192 个顶点缓冲区,减少 draw call
- **线条批处理**: 16384 个顶点,支持线宽变化时 flush
- **精灵批处理**: 10000 个精灵,使用单一 draw call
### 6.2 字体图集 (Font Atlas)
- 使用 `stb_rect_pack` 进行矩形打包
- 1024x1024 RGBA 纹理存储字形
- 动态缓存:首次使用字符时渲染到图集
### 6.3 坐标系
- **世界坐标**: Y轴向下 (0,0) 在左上角
- **纹理坐标**: OpenGL 标准,(0,0) 在左下角
- **相机**: 正交投影,可移动/缩放
### 6.4 渲染状态管理
- 自动处理 OpenGL 状态缓存
- 混合模式切换 (None/Alpha/Additive/Multiply)
- 变换矩阵栈支持嵌套变换
## 7. 使用示例
```cpp
// 1. 初始化
AppConfig config = AppConfig::createDefault();
config.windowConfig.title = "My Game";
Application::get().init(config);
// 2. 初始化渲染
GLRenderer renderer;
renderer.init(sdlWindow);
// 3. 加载字体
GLFontAtlas font("C:/Windows/Fonts/arial.ttf", 24);
// 4. 游戏循环
while (running) {
// 处理事件...
// 开始渲染
renderer.beginFrame(Color(0.1f, 0.1f, 0.15f, 1.0f));
renderer.setViewProjection(camera.getViewProjectionMatrix());
// 绘制图形
renderer.fillRect(Rect(100, 100, 200, 150), Colors::Red);
renderer.fillCircle(Vec2(400, 300), 50.0f, Colors::Blue, 32);
renderer.drawLine(Vec2(0, 0), Vec2(800, 600), Colors::White, 2.0f);
// 绘制文字
renderer.beginSpriteBatch();
renderer.drawText(font, "Hello World!", 100, 100, Colors::White);
renderer.endSpriteBatch();
// 结束渲染
renderer.endFrame();
SDL_GL_SwapWindow(sdlWindow);
}
// 5. 清理
renderer.shutdown();
Application::get().shutdown();
```