游戏人生
首页
(current)
GameDevTools
登陆
|
注册
个人中心
注销
游戏引擎 浅入浅出
Introduction
Introduction
前言
前言
1. 游戏引擎框架介绍
1. 游戏引擎框架介绍
1.1 Unity的组成
1.2 游戏引擎组成
2. Opengl开发环境搭建
2. Opengl开发环境搭建
2.1 Opengl到底是什么
2.2 搭建Opengl开发环境
2.3 使用VisualStudio开发
3. 绘制多边形
3. 绘制多边形
3.1 画个三角形
3.2 画个正方形
3.3 画个立方体
4. 着色器
4. 着色器
4.1 Unity Shader和OpenGL Shader
4.2 顶点着色器
4.3 片段着色器
5. 绘制贴图
5. 绘制贴图
5.1 颜色和贴图
5.2 贴图文件介绍
5.3 CPU与GPU的通信方式
5.4 使用stb_image解析图片
5.5 绘制带贴图的立方体盒子
5.6 压缩纹理
5.7 图片压缩工具
5.8 使用压缩纹理
5.9 DXT压缩纹理扩展
6. 索引与缓冲区对象
6. 索引与缓冲区对象
6.1 顶点索引
6.2 缓冲区对象
6.3 OpenGL Core Profile
6.4 顶点数组对象
7. 绘制Mesh和材质
7. 绘制Mesh和材质
7.1 导出Mesh文件
7.2 使用Mesh文件
7.3 Shader文件创建与使用
7.4 创建材质
7.5 使用材质
7.6 MeshRenderer
8. 绘制静态模型
8. 绘制静态模型
8.1 Blender安装与配置
8.2 Blender制作模型
8.3 Blender Python设置开发环境
8.4 Blender Python创建物体
8.5 Blender Python导出顶点数据
8.6 加载导出的Mesh
9. 基于组件开发
9. 基于组件开发
9.1 基于RTTR实现反射
9.2 实现GameObject-Component
10. 相机
10. 相机
10.1 最简单的相机
10.2 多相机渲染
10.3 相机排序
10.4 CullingMask
11. 控制系统
11. 控制系统
11.1 键盘控制
11.2 鼠标控制
12. 拆分引擎和项目
12. 拆分引擎和项目
13. 绘制文字
13. 绘制文字
13.1 TrueType简介
13.2 绘制单个字符
13.3 绘制多个文字
13.4 彩色字
14. GUI
14. GUI
14.1 正交相机
14.2 UIImage
14.3 UIMask
14.4 UIText
14.5 UIButton
15. 播放音效
15. 播放音效
15.1 播放2D音效
15.2 播放3D音效
15.3 使用FMOD Studio音频引擎
16. Profiler
16. Profiler
16.1 初识easy_profiler
16.2 集成easy_profiler
17. 嵌入Lua
17. 嵌入Lua
17.1 Sol2与C++交互
17.2 更加友好的Lua框架设计
17.3 引擎集成sol2
17.4 调试Lua
18. 骨骼动画
18. 骨骼动画
18.1 Blender制作骨骼动画
18.2 Blender导出骨骼动画
18.3 解析骨骼动画
18.4 矩阵的主序
19. 骨骼蒙皮动画
19. 骨骼蒙皮动画
19.1 骨骼蒙皮动画实现
19.2 骨骼权重
19.3 Blender蒙皮刷权重
19.4 Blender导出蒙皮权重
19.5 加载权重文件
20. 解析FBX文件
20. 解析FBX文件
20.1 导出Mesh
20.2 导出骨骼动画
20.3 导出权重
20.4 渲染骨骼蒙皮动画
21. 多线程渲染
21. 多线程渲染
21.1 GLFW多线程渲染
21.2 基于任务队列的多线程渲染
21.3 完全异步的多线程模型
21.4 引擎支持多线程渲染
22. Physx物理引擎
22. Physx物理引擎
22.1 Physx实例-小球掉落
22.2 物理材质
22.3 碰撞检测
22.4 连续碰撞检测
22.5 场景查询
22.6 引擎集成Physx
23. 经典光照
23. 经典光照
23.1 环境光
23.2 漫反射光照模型
23.3 镜面高光光照模型
23.4 高光贴图
23.5 Shader结构体
23.6 Uniform Buffer Object
23.7 方向光
23.8 点光源
23.9 多光源
24. 引擎编辑器的实现
24. 引擎编辑器的实现
24.1 分析Godot引擎编辑器
24.2 FBO RenderTexture GameTurbo DLSS
24.3 ImGui介绍与使用
24.4 分离引擎核心层和应用层
24.5 使用ImGui实现引擎编辑器
24.6 Hierarchy与Inspector面板
24.7 Geometry Buffer
25. Shadow Mapping
25. Shadow Mapping
25.1 深度图
25.2 简单阴影
88. VSCode扩展开发与定制
88. VSCode扩展开发与定制
88.1 第一个VSCode扩展程序
88.2 从源码编译VSCode
88.3 打包VSCode内置扩展
88.4 打包LuaHelper到Code-OSS
89. Doxygen生成API文档
89. Doxygen生成API文档
90. GPU分析工具
90. GPU分析工具
90.1 RenderDoc分析不显示bug
98. SubstancePainter插件开发
98. SubstancePainter插件开发
98.1 SP插件开发环境
98.2 开发SP功能性插件
98.3 开发SP渲染插件
99. Toolbag插件开发
99. Toolbag插件开发
99.1 插件开发环境
99.2 API介绍
99.3 命令行调用Toolbag
99.4 更多实现
99.5 代码参考
附录1. Wwise音频引擎
附录1. Wwise音频引擎
1.1 Wwise名词概念
1.2 Wwise制作音效导出SoundBank
1.3 集成Wwise
1.4 封装Wwise播放3D音效
1.5 Wwise性能分析器介绍
1.6 猎人开发后记
代码资源下载
点我下载
Github
点赞、收藏、关注
目录
<< 21.2 基于任务队列的多线程渲染
21.4 引擎支持多线程渲染 >>
## 21.3 完全异步的多线程模型 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```bash CLion项目文件位于 samples\multithread_render\gpu_resource_handle ``` 当我沿用上一节的多线程模型继续往下开发时,遇到了一个无法解决的问题。 为了性能,需要尽可能的将渲染任务设置为非阻塞的,非阻塞任务意味着我无法从渲染线程获得反馈。 以创建VAO为例,主线程发出创建VAO非阻塞任务,然后我没办法使用它,因为想使用它就需要VAO的ID。 这就是GPU资源管理问题。 这让我想起了以前在游戏中写的资源异步加载,每个加载任务都会创建一个Handle与之对应,这种设计模式也可以照搬到多线程渲染。 下面看下基于Handle的多线程同步模式。 ### 1. 基于Handle的同步模型原理 仍然以创建VAO为例,主线程发出创建VAO非阻塞任务时,先创建一个VAO Handle。渲染线程创建VAO后,将Handle与VAO ID映射起来,存放到HashMap中。 主线程发出使用VAO非阻塞任务时,携带Handle作为参数。渲染线程拿到Handle,从HashMap找到对应的VAO ID,去使用。 ### 2. 映射关系管理 我这里使用自增的Index来作为Handle,每一种GPU资源都分配单独的Index。 ```c++ //file:gpu_resource_mapper.h #ifndef UNTITLED_GPU_RESOURCE_MAPPER_H #define UNTITLED_GPU_RESOURCE_MAPPER_H #include <unordered_map> #include <glad/gl.h> /// GPU资源管理,负责管理GPU资源ID与其在引擎逻辑ID的映射关系。 class GPUResourceMapper { public: /// 生成Shader程序句柄 /// \return static unsigned int GenerateShaderProgramHandle(){ return ++shader_program_index_; } /// 生成VAO句柄 /// \return static unsigned int GenerateVAOHandle(){ return ++vao_index_; } /// 映射Shader程序 /// \param shader_program_handle /// \param shader_program_id static void MapShaderProgram(unsigned int shader_program_handle, GLuint shader_program_id){ shader_program_map_[shader_program_handle] = shader_program_id; } /// 映射VAO /// \param vao_handle /// \param vao_id static void MapVAO(unsigned int vao_handle, GLuint vao_id){ vao_map_[vao_handle] = vao_id; } /// 获取Shader程序 /// \param shader_program_handle /// \return static GLuint GetShaderProgram(unsigned int shader_program_handle){ return shader_program_map_[shader_program_handle]; } /// 获取VAO /// \param vao_handle /// \return static GLuint GetVAO(unsigned int vao_handle){ return vao_map_[vao_handle]; } private: static unsigned int shader_program_index_;//Shader程序索引 static unsigned int vao_index_;//VAO索引 static std::unordered_map<unsigned int, GLuint> shader_program_map_;//Shader程序映射表 static std::unordered_map<unsigned int, GLuint> vao_map_;//VAO映射表 }; #endif //UNTITLED_GPU_RESOURCE_MAPPER_H ``` ### 3. 生成Handle 对创建VAO任务结构进行改造,删除需要回传的参数,新增VAO句柄字段 `vao_handle_`。 ```c++ //file:render_task_type.h line:53 /// 创建VAO任务 class RenderTaskCreateVAO: public RenderTaskBase{ public: RenderTaskCreateVAO(){ render_command_=RenderCommand::CREATE_VAO; } ~RenderTaskCreateVAO(){} public: unsigned int shader_program_handle_=0;//着色器程序句柄 const void* positions_=nullptr;//顶点位置 GLsizei positions_stride_=0;//顶点数据大小 const void* colors_=nullptr;//顶点颜色 GLsizei colors_stride_=0;//颜色数据大小 unsigned int vao_handle_=0;//VAO句柄 }; ``` 在主线程创建VAO任务时,先生成VAO Handle,将其作为任务参数。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> ```c++ //file:main.cpp line:50 int main(void) { ...... //创建缓冲区任务 vao_handle_=GPUResourceMapper::GenerateVAOHandle(); RenderTaskProducer::ProduceRenderTaskCreateVAO(shader_program_handle_, kPositions, sizeof(glm::vec3), kColors, sizeof(glm::vec4), vao_handle_); ...... } ``` ### 4. Handle映射到GPU资源 渲染线程创建VAO之后,将VAO Handle映射到VAO ID。 ```c++ //file:render_task_consumer.cpp line:92 /// 创建VAO /// \param task_base void RenderTaskConsumer::CreateVAO(RenderTaskBase* task_base){ RenderTaskCreateVAO* task= dynamic_cast<RenderTaskCreateVAO*>(task_base); //从映射表中,获取Shader程序句柄 GLuint shader_program= GPUResourceMapper::GetShaderProgram(task->shader_program_handle_); GLuint vbo_pos,vbo_color,vao; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo_pos); glGenBuffers(1, &vbo_color); GLint attribute_pos_location = glGetAttribLocation(shader_program, "a_pos"); GLint attribute_col_location = glGetAttribLocation(shader_program, "a_color"); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo_pos); glBufferData(GL_ARRAY_BUFFER, sizeof(kPositions), kPositions, GL_STATIC_DRAW); glVertexAttribPointer(attribute_pos_location, 3, GL_FLOAT, false, sizeof(glm::vec3), (void*)0); glEnableVertexAttribArray(attribute_pos_location);//启用顶点Shader属性(a_pos),指定与顶点坐标数据进行关联 glBindBuffer(GL_ARRAY_BUFFER, vbo_color); glBufferData(GL_ARRAY_BUFFER, sizeof(kColors), kColors, GL_STATIC_DRAW); glVertexAttribPointer(attribute_col_location, 3, GL_FLOAT, false, sizeof(glm::vec4), (void*)0); glEnableVertexAttribArray(attribute_col_location);//启用顶点Shader属性(a_color),指定与顶点颜色数据进行关联 glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); //将主线程中产生的VAO句柄 映射到 VAO GPUResourceMapper::MapVAO(task->vao_handle_,vao); } ``` ### 5. 使用Handle 当绘制三角形任务时,带上VAO Handle作为参数。 ```c++ //file:main.cpp line:74 void Render(){ //绘制任务 RenderTaskProducer::ProduceRenderTaskDrawArray(shader_program_handle_, vao_handle_); } ``` 在渲染线程中,由VAO Handle找到VAO ID,然后再绑定进行绘制。 ```c++ //file:render_task_consumer.cpp line:127 /// 绘制 /// \param task_base /// \param projection /// \param view void RenderTaskConsumer::DrawArray(RenderTaskBase* task_base, glm::mat4& projection, glm::mat4& view){ RenderTaskDrawArray* task= dynamic_cast<RenderTaskDrawArray*>(task_base); //从映射表中,获取Shader程序句柄 GLuint shader_program= GPUResourceMapper::GetShaderProgram(task->shader_program_handle_); //从映射表中,获取VAO GLuint vao= GPUResourceMapper::GetVAO(task->vao_handle_); //指定Shader程序 glUseProgram(shader_program); { glBindVertexArray(vao); //上传顶点数据并进行绘制 glDrawArrays(GL_TRIANGLES, 0, 3); } } ``` ### 6. 测试 
<< 21.2 基于任务队列的多线程渲染
21.4 引擎支持多线程渲染 >>
12
代码资源下载
点我下载
Github
点赞、收藏、关注
目录
Introduction
Introduction
前言
前言
1. 游戏引擎框架介绍
1. 游戏引擎框架介绍
1.1 Unity的组成
1.2 游戏引擎组成
2. Opengl开发环境搭建
2. Opengl开发环境搭建
2.1 Opengl到底是什么
2.2 搭建Opengl开发环境
2.3 使用VisualStudio开发
3. 绘制多边形
3. 绘制多边形
3.1 画个三角形
3.2 画个正方形
3.3 画个立方体
4. 着色器
4. 着色器
4.1 Unity Shader和OpenGL Shader
4.2 顶点着色器
4.3 片段着色器
5. 绘制贴图
5. 绘制贴图
5.1 颜色和贴图
5.2 贴图文件介绍
5.3 CPU与GPU的通信方式
5.4 使用stb_image解析图片
5.5 绘制带贴图的立方体盒子
5.6 压缩纹理
5.7 图片压缩工具
5.8 使用压缩纹理
5.9 DXT压缩纹理扩展
6. 索引与缓冲区对象
6. 索引与缓冲区对象
6.1 顶点索引
6.2 缓冲区对象
6.3 OpenGL Core Profile
6.4 顶点数组对象
7. 绘制Mesh和材质
7. 绘制Mesh和材质
7.1 导出Mesh文件
7.2 使用Mesh文件
7.3 Shader文件创建与使用
7.4 创建材质
7.5 使用材质
7.6 MeshRenderer
8. 绘制静态模型
8. 绘制静态模型
8.1 Blender安装与配置
8.2 Blender制作模型
8.3 Blender Python设置开发环境
8.4 Blender Python创建物体
8.5 Blender Python导出顶点数据
8.6 加载导出的Mesh
9. 基于组件开发
9. 基于组件开发
9.1 基于RTTR实现反射
9.2 实现GameObject-Component
10. 相机
10. 相机
10.1 最简单的相机
10.2 多相机渲染
10.3 相机排序
10.4 CullingMask
11. 控制系统
11. 控制系统
11.1 键盘控制
11.2 鼠标控制
12. 拆分引擎和项目
12. 拆分引擎和项目
13. 绘制文字
13. 绘制文字
13.1 TrueType简介
13.2 绘制单个字符
13.3 绘制多个文字
13.4 彩色字
14. GUI
14. GUI
14.1 正交相机
14.2 UIImage
14.3 UIMask
14.4 UIText
14.5 UIButton
15. 播放音效
15. 播放音效
15.1 播放2D音效
15.2 播放3D音效
15.3 使用FMOD Studio音频引擎
16. Profiler
16. Profiler
16.1 初识easy_profiler
16.2 集成easy_profiler
17. 嵌入Lua
17. 嵌入Lua
17.1 Sol2与C++交互
17.2 更加友好的Lua框架设计
17.3 引擎集成sol2
17.4 调试Lua
18. 骨骼动画
18. 骨骼动画
18.1 Blender制作骨骼动画
18.2 Blender导出骨骼动画
18.3 解析骨骼动画
18.4 矩阵的主序
19. 骨骼蒙皮动画
19. 骨骼蒙皮动画
19.1 骨骼蒙皮动画实现
19.2 骨骼权重
19.3 Blender蒙皮刷权重
19.4 Blender导出蒙皮权重
19.5 加载权重文件
20. 解析FBX文件
20. 解析FBX文件
20.1 导出Mesh
20.2 导出骨骼动画
20.3 导出权重
20.4 渲染骨骼蒙皮动画
21. 多线程渲染
21. 多线程渲染
21.1 GLFW多线程渲染
21.2 基于任务队列的多线程渲染
21.3 完全异步的多线程模型
21.4 引擎支持多线程渲染
22. Physx物理引擎
22. Physx物理引擎
22.1 Physx实例-小球掉落
22.2 物理材质
22.3 碰撞检测
22.4 连续碰撞检测
22.5 场景查询
22.6 引擎集成Physx
23. 经典光照
23. 经典光照
23.1 环境光
23.2 漫反射光照模型
23.3 镜面高光光照模型
23.4 高光贴图
23.5 Shader结构体
23.6 Uniform Buffer Object
23.7 方向光
23.8 点光源
23.9 多光源
24. 引擎编辑器的实现
24. 引擎编辑器的实现
24.1 分析Godot引擎编辑器
24.2 FBO RenderTexture GameTurbo DLSS
24.3 ImGui介绍与使用
24.4 分离引擎核心层和应用层
24.5 使用ImGui实现引擎编辑器
24.6 Hierarchy与Inspector面板
24.7 Geometry Buffer
25. Shadow Mapping
25. Shadow Mapping
25.1 深度图
25.2 简单阴影
88. VSCode扩展开发与定制
88. VSCode扩展开发与定制
88.1 第一个VSCode扩展程序
88.2 从源码编译VSCode
88.3 打包VSCode内置扩展
88.4 打包LuaHelper到Code-OSS
89. Doxygen生成API文档
89. Doxygen生成API文档
90. GPU分析工具
90. GPU分析工具
90.1 RenderDoc分析不显示bug
98. SubstancePainter插件开发
98. SubstancePainter插件开发
98.1 SP插件开发环境
98.2 开发SP功能性插件
98.3 开发SP渲染插件
99. Toolbag插件开发
99. Toolbag插件开发
99.1 插件开发环境
99.2 API介绍
99.3 命令行调用Toolbag
99.4 更多实现
99.5 代码参考
附录1. Wwise音频引擎
附录1. Wwise音频引擎
1.1 Wwise名词概念
1.2 Wwise制作音效导出SoundBank
1.3 集成Wwise
1.4 封装Wwise播放3D音效
1.5 Wwise性能分析器介绍
1.6 猎人开发后记