游戏人生
首页
(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面板
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
点赞、收藏、关注
目录
<< 9.1 基于RTTR实现反射
10. 相机 >>
## 9.2 实现GameObject-Component ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```c++ CLion项目文件位于 samples\component\gameobject_component ``` 上一节验证了RTTR反射功能之后,就可以制定基于组件开发的具体方案了,参照Unity的GameObject-Component结构,具体如下: 1. 实现GameObject。 2. 实现Component,其他组件(如 Transform)都继承自Component。 3. 通过组件类名,实例化组件,存储到GameObject的容器中。 落实到具体,分别创建了以下代码文件: 1. 框架基础:game_object.h、component.h 2. 自定义组件:transform.h 下面逐个介绍代码实现。 ### 1.框架基础实现 #### 1.1 GameObject 大家都知道人是一个东西,但是东西是一种虚拟的描述,它需要附加实实在在的东西。 想让人被看见,就需要附加肌肉外形。 想让人运动,就需要附加骨架。 想让人漂亮,就需要附加衣服。 想让人有内涵,就需要附加AI。 我常将GameObject比喻为人,他可以附加各种具体的组件,来实现它的百变。 附加上Transform,就可以设置位置。 附加上MeshRenderer和MeshFilter,就可以显示出各种形状。 附加上SkinnedMeshRenderer,就可以动起来。 附加上CharacterController,就可以控制它移动。 组件既可以添加,也可以随时被移除,而且同名组件可以添加多个,因此用下面的容器来存储组件: ```c++ ///file:source/component/game_object.h line:41 std::unordered_map<std::string,std::vector<Component*>> component_type_instance_map_; ``` 新增以下API用来对组件列表进行读写: ```c++ ///file:source/component/game_object.h line:27 /// 添加组件 /// \param component_type_name 组件类名 /// \return Component* AddComponent(std::string component_type_name); /// 获取组件 /// \param component_type_name 组件类名 /// \return Component* GetComponent(std::string component_type_name); ``` 在`AddComponent()`,根据组件名,调用RTTR反射获取组件构造函数,创建组件实例。 ```c++ ///file:source/component/game_object.cpp line:23 Component* GameObject::AddComponent(std::string component_type_name) { type t = type::get_by_name(component_type_name); variant var = t.create(); // 创建实例 Component* component=var.get_value<Component*>(); component->set_game_object(this); ...... return component; } ``` #### 1.2 Component Component是所有组件的基类,只需要保存对GameObject的引用即可,具体的功能都由子类实现。 ```c++ ///file:source/component/component.h line:12 class Component { public: Component(); ~Component(); GameObject* game_object(){return game_object_;} void set_game_object(GameObject* game_object){game_object_=game_object;} private: GameObject* game_object_; }; ``` ### 2.自定义组件Transform实现 Transform负责坐标、旋转、缩放这3个基础属性,代码如下: ```c++ ///file:source/component/transform.h line:11 class Transform : public Component{ public: Transform(); ~Transform(); glm::vec3 position() const {return position_;} glm::vec3 rotation() const {return rotation_;} glm::vec3 scale() const {return scale_;} void set_position(glm::vec3 position){position_=position;} void set_rotation(glm::vec3 rotation){rotation_=rotation;} void set_scale(glm::vec3 scale){scale_=scale;} private: glm::vec3 position_; glm::vec3 rotation_; glm::vec3 scale_; }; ``` 需要注意的是,Transform是一个组件,它的实例化是通过`go->AddComponent("Transform")`挂在到Gameobject上,通过类名创建类实例,所以Transform需要进行RTTR注册反射。 ```c++ ///file:source/component/transform.cpp line:8 using namespace rttr; RTTR_REGISTRATION//注册反射 { registration::class_<Transform>("Transform") .constructor<>()(rttr::policy::ctor::as_raw_ptr) .property("position", &Transform::position, &Transform::set_position) .property("rotation", &Transform::rotation, &Transform::set_rotation) .property("scale", &Transform::scale, &Transform::set_scale); } Transform::Transform() { } Transform::~Transform() { } ``` ### 3.改造MeshFilter、MeshRenderer MeshFilter 加载Mesh文件,向MeshRenderer提供顶点数据。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> MeshRenderer 从MeshFilter拿到顶点数据上传GPU生成VBO用于渲染。 在之前的章节实例中,需要向MeshRenderer指定MeshFilter,并且需要在外部计算好MVP矩阵,才能在Renderer()函数中上传GPU渲染: ```c++ ///file: samples/export_blender/load_mesh_from_blender/source/main.cpp line:50 int main(void) { ...... MeshFilter* mesh_filter=new MeshFilter(); mesh_filter->LoadMesh("model/fishsoup_pot.mesh"); ...... MeshRenderer* mesh_renderer=new MeshRenderer(); mesh_renderer->SetMeshFilter(mesh_filter);//向MeshRenderer指定MeshFilter: ...... while (!glfwWindowShouldClose(window)) { ...... glm::mat4 trans = glm::translate(glm::vec3(0,0,0)); static float rotate_eulerAngle=0.f; rotate_eulerAngle+=0.1f; glm::mat4 rotation = glm::eulerAngleYXZ(glm::radians(rotate_eulerAngle), glm::radians(0.f), glm::radians(0.f)); glm::mat4 scale = glm::scale(glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 model = trans*scale*rotation; glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0,0), glm::vec3(0, 1, 0)); glm::mat4 projection=glm::perspective(glm::radians(60.f),ratio,1.f,1000.f); glm::mat4 mvp=projection*view*model; mesh_renderer->SetMVP(mvp);//外部计算好MVP矩阵 mesh_renderer->Render(); ...... } ...... } ``` 组件化之后,坐标、旋转、缩放信息都存在Transform组件中,以及组件形式存在的MeshFilter,都可以由MeshRenderer向GameObject主动获取。 来看具体逻辑。 #### 3.1 向RTTR注册 两者都需要向RTTR注册,才能通过类名 创建实例。 #### 3.2 MeshRenderer主动获取Transform && MeshFilter MeshFilter和MeshRenderer是同一个GameObject上的组件,通过`GetComponent`就可以获取。 ```c++ ///file:source/renderer/mesh_renderer.cpp line:39 void MeshRenderer::Render() { //主动获取 Transform 组件,计算mvp。 auto component_transform=game_object()->GetComponent("Transform"); auto transform=dynamic_cast<Transform*>(component_transform); if(!transform){ return; } glm::mat4 trans = glm::translate(transform->position()); auto rotation=transform->rotation(); glm::mat4 eulerAngleYXZ = glm::eulerAngleYXZ(glm::radians(rotation.y), glm::radians(rotation.x), glm::radians(rotation.z)); glm::mat4 scale = glm::scale(transform->scale()); //缩放; glm::mat4 model = trans*scale*eulerAngleYXZ; glm::mat4 mvp=projection_*view_*model; //主动获取 MeshFilter 组件 auto component_meshfilter=game_object()->GetComponent("MeshFilter"); auto mesh_filter=dynamic_cast<MeshFilter*>(component_meshfilter); if(!mesh_filter){ return; } ...... } ``` ### 4. 使用GameObject-Component 组件不能直接`new`了,必须通过`AddComponent`的形式挂到GameObject上。 修改`main.cpp`,将原来通过`new`实例化的代码,修改为组件形式。 ```c++ ///file:source/main.cpp line:54 int main(void) { ...... //创建GameObject GameObject* go=new GameObject("something"); //挂上 Transform 组件 auto transform=dynamic_cast<Transform*>(go->AddComponent("Transform")); //挂上 MeshFilter 组件 auto mesh_filter=dynamic_cast<MeshFilter*>(go->AddComponent("MeshFilter")); mesh_filter->LoadMesh("model/fishsoup_pot.mesh"); //挂上MeshRenderer 组件 auto mesh_renderer=dynamic_cast<MeshRenderer*>(go->AddComponent("MeshRenderer")); Material* material=new Material();//设置材质 material->Parse("material/fishsoup_pot.mat"); mesh_renderer->SetMaterial(material); while (!glfwWindowShouldClose(window)) { ...... glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0,0), glm::vec3(0, 1, 0)); glm::mat4 projection=glm::perspective(glm::radians(60.f),ratio,1.f,1000.f); mesh_renderer->SetView(view); mesh_renderer->SetProjection(projection); mesh_renderer->Render(); ...... } ...... } ``` ### 5.测试 将项目组件化之后,再来运行测试一下,看看是否正常。  没啥问题!
<< 9.1 基于RTTR实现反射
10. 相机 >>
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面板
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 猎人开发后记