基于OpenGL4.6实现的渲染引擎
项目源码编码为UTF8
- 设计项目结构
- 修改相机控制方案
- 改用SDL3管理窗口
- 数据加载和管理
- 场景管理,以model为单位
- 资源管理方式采用全局ID和name
- 统一顶点属性格式,设置固定格式shader
- 绘制网格
- 添加所有纹理
- 添加光照
- skyBox(6面图和hdr)
- 反射环境光
- 实现PBR材质
- PBR的IBL
- 日志 spdlog模块
- imgui模块
- 阴影
- HDR
- 后处理(泛光)
- 调整结构
- 光追渲染管线
- 资源加载异步化
- wasdqe操作相机
- 鼠标拖拽旋转相机
[ Application / Game Layer ]
├─ GameLogic / Editor / Script
└─ 使用 SceneManager 创建对象、控制 RenderManager 渲染
│
▼
[ Engine Layer ]
├─ Engine
│ ├─ 初始化/更新/销毁各模块
│ └─ 主循环(Update → Render)
│
├─ SceneManager
│ ├─ SceneObject / Entity
│ │ ├─ Transform (位置/旋转/缩放)
│ │ ├─ MeshRef → ResourceManager.Mesh
│ │ └─ MaterialRef → ResourceManager.Material
│ ├─ Camera
│ └─ Light
│
├─ ResourceManager
│ ├─ Mesh (顶点/索引/法线/UV)
│ ├─ Material (Shader + 参数)
│ └─ Texture
│
├─ RenderManager
│ ├─ 遍历 SceneObjects
│ ├─ 构建 DrawCall / RenderCommand
│ └─ 提交 CommandList 到 RHI
│
└─ Display/WindowManager
├─ 窗口创建/销毁
└─ 输入事件处理
│
▼
[ RHI Layer ]
├─ Buffer (Vertex/Index/Uniform)
├─ Texture (GPU纹理)
├─ Shader
├─ Pipeline (绑定Shader + RenderState + VertexLayout)
└─ CommandList (绘制命令)
│
▼
[ Platform Layer ]
├─ OS API (Win32, Cocoa, X11)
└─ GPU API (OpenGL, Vulkan, DX12, Metal)
Application/Game Layer
↓
Engine Layer
├── SceneManager → 遍历对象
├── ResourceManager → 提供 Mesh/Material/Texture 数据
├── RenderManager → 构建 DrawCalls
↓
RHI Layer
├── Buffer / Texture / Shader / Pipeline
└── CommandList → GPU 指令
↓
Platform Layer
├── OS API → 窗口、输入
└── GPU API → 实际提交渲染
ResourceManager (CPU 数据)
│
SceneObject 引用 CPU 数据
│
RenderManager / MeshGPU
│ 调用
▼
RHI (Buffer/Texture/Shader)
│
GPU API 提交
▼
GPU 渲染
MyRenderingEngine
|-- resources
| |-- PointCloud # 点云文件
| |-- scenes # Scene description files in JSON format
| |-- shaders
| | |-- computeShaders # Compute shaders for clustered forward
| | |-- OldShaders # Shaders not currently in use
| | `-- currentShaders # Shaders for the current rendering pipeline
| `-- skyboxes # Skyboxes in either cubemap or equirectangular map form
|-- build # CMake compile
|-- include # Project header files
|-- libs # Check dependencies section for descriptions & links
| |-- ASSIMP
| |-- Dear imgui
| |-- Glad
| |-- Json c++
| |-- GLI
| |-- stb_image
| `-- SDL2
|-- modules # CMake lib setup scripts
|-- src # C++ implementation files
`-- CMakeLists.txt # CMake build script
RenderPipeline
一套固定的渲染状态 + 着色器组合(比如 ForwardPipeline、LightingPipeline)。
可以理解为“一个小模块,定义了怎么画”。
RenderPass
定义“画在哪里”,绑定哪些 framebuffer/attachments(颜色、深度、G-buffer 等)。
一个 pass 通常会调用若干个 pipeline。
例如:Deferred 的 GeometryPass + LightingPass。
RenderGraph / Renderer(渲染流程)
定义多个 pass 的执行顺序和依赖关系(比如:几何 → 光照 → 后处理 → UI)。
知道哪些 Pass 要先执行、哪些 Buffer 要作为输入输出。
本质上是一个 调度器。
RenderManager / Engine 层
站在引擎最上层,负责管理场景、相机、资源加载。
它不直接关心每个 pass 怎么画,只负责驱动 Renderer 去渲染一帧。
RenderManager(顶层)
|
└── Renderer(渲染器,FrameGraph 调度)
|
├── RenderPass(一个个阶段)
│ └── 调用对应的 RenderPipeline
│
└── FrameBuffer / Resource 管理
Pipeline:具体绘制方法
Pass:一个渲染阶段
Renderer(或 RenderGraph):管理所有 Pass 的执行顺序
RenderManager:顶层接口,调度 Renderer,但不关心细节
[ Application/Game Layer ]
- 游戏逻辑 / 编辑器 / 脚本
[ Engine Layer ]
- Engine (统一入口)
- SceneManager (场景管理:对象、相机、灯光)
- RenderManager (渲染调度:负责把场景绘制出来)
- ResourceManager (资源管理:模型、材质、纹理)
- Display/WindowManager (窗口系统 / 输入输出)
[ Render Hardware Interface (RHI) Layer ]
- Buffer / Texture / Shader / Pipeline / CommandList
[ Platform Layer ]
- OS API (Win32, Cocoa, X11)
- GPU API (OpenGL, Vulkan, DX12, Metal)
// 渲染调度
void RenderManager::render(SceneManager& sceneManager) {
Scene& scene = sceneManager.getActiveScene();
Camera& camera = scene.getCamera();
renderScene(scene,camera);
}
void RenderManager::renderScene(scene,camera){
useShaderProgram();
for (auto& model : passes) {
renderModel(model, camera);
}
}
void RenderManager::renderModel(model,camera){
vector<int> meshids= model.getmeshes();
vector<int> textureids= model.getmeshes();
setMat4("model",model.getModelMatrix());
for(int id:meshids){
renderMesh(id);
}
}
void RenderManager::renderMesh(meshid,){
meshgl = resourcemanager.getmeshgl(meshid)
bindMesh()
draw()
}
RenderPass(RHI);
Renderer (对外接口层)
│
├── ForwardRenderer
│ └── 使用 ForwardRenderPipeline
│ ├── ShadowPass
│ ├── GeometryPass
│ └── LightingPass
│
├── DeferredRenderer
│ └── 使用 DeferredRenderPipeline
│ ├── GBufferPass
│ ├── LightingPass
│ └── PostProcessPass
│
└── PathTracingRenderer
└── 使用 PathTracingPipeline
└── RayTracingPass
GameLoop
→ RenderEngine.render()
→ RenderManager.render(scene)
→ Renderer.render(scene)
→ RenderPass.execute(scene)
→ drawcall
与Assimp库类似
scene
|---Models
|---Meshs
|---vertices
|---indices
|---textures(texture的id)
RenderEngine(引擎核心)
作为全局的调度者,负责:
初始化图形 API(OpenGL / Vulkan / DX12)
创建/销毁窗口和上下文
管理 RenderManager / SceneManager / ResourceManager
驱动整个渲染帧循环(update → render → present)
它不直接管具体的绘制细节,只是调用 RenderManager 去执行渲染。
RenderManager(渲染子系统管理器)
负责真正的绘制流程:
从 Scene 中获取对象(ModelObject、LightObject、Camera)
组织渲染队列(比如按材质/透明度/距离排序)
上传数据到 GPU(Mesh VBO、Texture、UBO 等)
调用底层 API(glDraw*/vkCmdDraw 等)
可细分职责:
渲染准备阶段:清理缓冲区、设置 viewport
遍历场景对象:收集需要绘制的模型和光源
执行绘制:绑定 shader/program → 设置 uniform → draw call
后处理:bloom、shadow、HDR、tone mapping 等
- RenderEngine(引擎层)
- InputManager
- 交互管理,接收输入信号
- RenderManager
- 渲染管理,负责渲染场景,管理所有渲染所需资源和方法
- Manager类
- 总的来说Manager是一个资源缓存
- 持有同类资源的唯一副本,管理资源的生命周期(持有资源,使用共享指针)
- 临时持有资源(使用裸指针)
- 负责创建/加载资源,并保证同类资源的唯一性
- 提供访问资源的接口(返回资源引用)
- 资源索引方式(id,relativePath,name)
- relativePath防止资源重复加载
- name并非唯一标识符,但是目前没有管理name对应多个资源的情况,如果出现同名资源将会替换原来的资源
- GPU Resource Manager
- GPU 资源缓存
- 保存所有 GPU 资源的句柄(Buffer、Texture、Shader)
- GPU资源和对应的CPU资源采用相同ID管理(确保不会重复加载资源)
- CPU Resource Manager(CPU 资源)
- 提供多种查找方式(name,path(保证资源唯一性),id(唯一标识符))
- Scene Manager
- 场景
- SceneObject 可渲染对象
- ModelObject
- 持有绘制所需相关资源Id(meshid,textureid)
- 有自己的transform属性
- Model,Scene等组成部分均不实现draw函数,只是资源和资源状态的集合
- 所有对象都只存相关资源id,资源访问通过resourcemanager实现,绘制通过rendermanager实现
- ModelObject
- GPU API 抽象(RHI)
1. 开始渲染帧
2. 绑定Shader A → 渲染3D模型(处理光照、材质)
3. 解绑Shader A → 绑定Shader B → 渲染UI元素(简单正交投影)
4. 解绑Shader B → 绑定Shader C → 渲染粒子效果(加随机运动逻辑)
5. 解绑Shader C → 绑定Shader D → 执行后期处理(全屏模糊)
6. 结束渲染帧
// 假设已编译链接好三个Shader程序
GLuint modelShader = ...; // 3D模型Shader
GLuint uiShader = ...; // UI Shader
GLuint particleShader = ...;// 粒子Shader
// 渲染3D模型
glUseProgram(modelShader); // 切换到模型Shader
glBindVertexArray(modelVAO);
glDrawElements(GL_TRIANGLES, ...);
// 渲染UI
glUseProgram(uiShader); // 切换到UI Shader
glBindVertexArray(uiVAO);
glDrawArrays(GL_TRIANGLES, ...);
// 渲染粒子
glUseProgram(particleShader); // 切换到粒子Shader
glBindVertexArray(particleVAO);
glDrawArraysInstanced(GL_TRIANGLES, ...);SceneManager
└── Scene
├── Camera
├── Object[]
└── Light[]
RenderManager
└── Renderer[]
└── RenderPipeline
└── RenderPass[]
└── 调用 RenderContext (shader, fbo, state)
RenderContext
├── GPU state (blend, depth, cull)
├── Current shader
├── Current framebuffer
└── Resource bindings
ShaderManager
└── ShaderProgram("Phong")
├── VertexShader
└── FragmentShader
└── ShaderProgram("ShadowMap")
├── VertexShader
└── FragmentShader
└── ShaderProgram("ComputeParticles")
└── ComputeShader
Manager 不负责对象的构造,而是负责:
维护对象的生命周期(注册、引用计数、释放)
提供检索、查找、缓存复用等功能
提供统一的接口来访问已有资源
ShaderManager的职责,不同的场景或者需求可能需要不同的PipelineState,shadermanager主要用于防止重复编译相同的shader,而不是说统一管理shader,shader在PipelineState中高度定制化
- shader当前采用固定格式
可用方案:多套着色器,按需切换
为不同顶点格式的模型写不同的着色器。 比如: Shader_PosTex 处理只有位置+UV 的模型。 Shader_PosNormal 处理位置+法线的模型。 Shader_Full 处理位置+法线+UV+切线的模型。 渲染时,根据模型的顶点格式选择对应的 Shader。 优点:更高效,显存占用少。 缺点:Shader 数量爆炸,管理起来麻烦。
一个shader对应多种顶点格式 通过条件判断决定是否使用某些属性。 例如: layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; // 可选 layout (location = 2) in vec2 aTexCoord; // 可选
uniform bool useNormal; uniform bool useTexcoord;
void main() { if (useNormal) { ... } if (useTexcoord) { ... } } 加载模型时,如果模型没有某个属性 → 在 VAO 里给这个 attribute 禁用 (glDisableVertexAttribArray)。 优点:只需一套 Shader,灵活。 缺点:Shader 逻辑复杂,可能有分支开销。
- 当前使用全局唯一ID管理资源
可以考虑对象池 + Handle (index + generation) 的方式管理资源
- 当前模式为单线程
- 当前渲染管线为Forward(不支持透明物体)
- 当前未实现灯光管理
- 当前DrawCall模式为逐个对象绘制,可以考虑用Indirect Drawing的基本思路 OpenGL 提供了一种方式:把绘制命令本身(例如 indexCount、instanceCount、baseIndex、baseVertex、baseInstance 等)放进 GPU Buffer(GL_DRAW_INDIRECT_BUFFER), 然后用一次 API 调用,让 GPU 批量执行这些命令。 也就是说: 以前:CPU 多次调用 glDrawElements,把参数从 CPU 传给 GPU。 现在:CPU 一次调用 glMultiDrawElementsIndirect,GPU 从 buffer 中自己读出所有 draw 参数。
- 当前未实现后处理
- 当前未实现实例化渲染
CPU资源销毁时机
GPU资源销毁时机
skybox支持HDR格式
HybridRenderingEngine
C++实现的渲染器
RayTracing
