游戏人生
首页
(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
点赞、收藏、关注
目录
<< 1.3 集成Wwise
1.5 Wwise性能分析器介绍 >>
## 1.4 封装Wwise播放3D音效 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```bash CLion项目文件位于 samples\audio_wwise\integrate ``` 这一节介绍`AudioSource`、`AudioListener`对Wwise API的封装。 + AudioSource 音源,提供创建、播放、停止、设置回调等接口,是对Wwise Event的封装。 + AudioListener 听者。 在`22.2 Wwise制作音效导出SoundBank`这一节,制作了一个死亡音效并导出了SoundBank,这一节就用这个死亡音效来作为实例播放。 ### 1. AudioSource Wwise提供了接口 `AK::SoundEngine::PostEvent`来触发Event播放音效,并且返回 `AkPlayingID` 来作为当前正在播放的Event的Handle。 所以在AudioSource里,主要是提供对Event的播放,以及后续对`AkPlayingID`的后续操作。 ```c++ //file:source/audio/wwise/audio_source.h class AudioSource:public Component { public: AudioSource(); ~AudioSource(); /// 设置Event名 void SetEvent(const std::string &event_name); /// 设置实时控制参数 void SetRTPCValue(const std::string &realtime_parameter_control_name, float value); /// 播放 void Play(); /// 停止 void Stop(); /// 设置音效播放完成回调 /// @param callback 回调函数,如果是lua传入,使用普通function就行 void set_event_end_callback(std::function<void(void)> callback){ event_end_callback_ = callback; } private: void Awake() override; void Update() override; private: AkGameObjectID audio_object_id_; std::string event_name_; AkPlayingID playing_id_; std::function<void()> event_end_callback_;//AudioSource实例播放结束回调 /******************** 回调处理 ********************/ public: /// Event回调,静态函数 /// \param in_eType Event类型。 /// \param in_pCookie 回调参数,在PostEvent设置的,原样返回。 static void MusicCallback(AkCallbackType in_eType,AkCallbackInfo* in_pCallbackInfo); /// 处理AudioSource回调队列 static void ExecuteMusicCallbackQueue(); private: /// Event回调信息 class MusicCallbackInfo{ public: MusicCallbackInfo(AkCallbackType callback_type, AkCallbackInfo callback_info) :callback_type_(callback_type), callback_info_(callback_info){} ~MusicCallbackInfo(){} AkCallbackType callback_type_;//回调类型,停止、暂停、退出等事件枚举 AkCallbackInfo callback_info_;//回调参数,包括音频对象ID、透传参数。 }; static rigtorp::SPSCQueue<MusicCallbackInfo> event_callback_queue_;//AudioSource回调队列,单线程写单线程读,线程安全。 }; ``` `SetEvent` `Play` `Stop` 这几个API都挺简单的,就是调用上一节介绍的WwiseAudio 对应函数。 需要详细介绍的是: <font color=red>播放音效设置的事件监听回调,回调函数是在Wwise线程,不是在主线程。</font>  那么需要用一个多线程共享队列来存储事件回调,然后在主线程Update从队列中取出事件回调来处理。 ```c++ //file:source/audio/wwise/audio_source.h line:60 private: /// Event回调信息 class MusicCallbackInfo{ public: MusicCallbackInfo(AkCallbackType callback_type, AkCallbackInfo callback_info) :callback_type_(callback_type), callback_info_(callback_info){} ~MusicCallbackInfo(){} AkCallbackType callback_type_;//回调类型,停止、暂停、退出等事件枚举 AkCallbackInfo callback_info_;//回调参数,包括音频对象ID、透传参数。 }; static rigtorp::SPSCQueue<MusicCallbackInfo> event_callback_queue_;//AudioSource回调队列,单线程写单线程读,线程安全。 ``` 这里引入`rigtorp::SPSCQueue`这个库,它是多线程安全的,支持一个生产者,一个消费者同时访问。 当Wwise调用回调函数时,实例化 `MusicCallbackInfo`,然后存入`event_callback_queue_`。 ```c++ //file:source/audio/wwise/audio_source.cpp line:67 /// Event回调,静态函数 /// \param in_eType Event类型。 /// \param in_pCookie 回调参数,在PostEvent设置的,原样返回。 void AudioSource::MusicCallback(AkCallbackType in_eType,AkCallbackInfo* in_pCallbackInfo) { MusicCallbackInfo music_callback_info(in_eType,*in_pCallbackInfo); event_callback_queue_.push(music_callback_info); } /// 处理AudioSource回调队列 void AudioSource::ExecuteMusicCallbackQueue() { while (event_callback_queue_.front()){ MusicCallbackInfo* music_callback_info = event_callback_queue_.front(); AudioSource* audio_source=(AudioSource*)music_callback_info->callback_info_.pCookie; if(music_callback_info->callback_type_ == AK_EndOfEvent){ DEBUG_LOG_INFO("end event: {}",audio_source->event_name_); if(audio_source->event_end_callback_){ audio_source->event_end_callback_(); } } event_callback_queue_.pop(); } } ``` 然后在主线程Update时,从队列中取出,再处理。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> ```c++ //file:source/audio/wwise/audio_source.cpp line:54 void AudioSource::Update() { Component::Update(); // 处理Event ExecuteMusicCallbackQueue(); ...... } ``` 另外需要在Update里面更新Wwise GameObject的坐标以及朝向,不然得不到3D音效。 ### 2. AudioListener AudioListener只是一个坐标抽象表示,所以只需要创建Wwise GameObject。 也需要在Update里面更新Wwise GameObject的坐标以及朝向。 ```c++ //file:source/audio/wwise/audio_listener.cpp void AudioListener::Awake() { audio_listener_object_id_=WwiseAudio::GeneratorGameObjectID(); WwiseAudio::CreateAudioObject(audio_listener_object_id_,game_object()->name().c_str()); WwiseAudio::SetDefaultListeners(audio_listener_object_id_); } void AudioListener::Update() { Component::Update(); auto component_transform=game_object()->GetComponent("Transform"); auto transform=dynamic_cast<Transform*>(component_transform); if(!transform){ return; } auto pos=transform->position(); // 设置Wwise GameObject位置、朝向 WwiseAudio::SetPosition(audio_listener_object_id_,pos,glm::vec3(0,0,1),glm::vec3(0,1,0)); } ``` ### 3. 实例播放3D音效 在`22.2 Wwise制作音效导出SoundBank`这一节,制作了的死亡音效。 现在测试加载了导出的Bank,并创建`AudioSource`、`AudioListener`实例,触发Event播放音效。 在实例中,创建了一个怪物,附加了`AudioSource`并指定了Event。 创建了多个怪物坐标,当按下键盘空格之后设置到新坐标,然后触发Event播放音效,这样可以对比听出3D的效果。 具体代码如下: ```lua --file:example/game_scene.lua GameScene={ go_camera_ui_,--摄像机UI go_ui_image_,--UI图片 listener_go_,--Listener monster_go_,--怪物 monster_pos_array_,--怪物位置 monster_pos_index_,--怪物位置索引 } -- ...... -- public: function GameScene:Awake() -- 加载Init.bank文件 WwiseAudio.LoadBank("Init.bnk") -- 加载游戏音效bank文件 WwiseAudio.LoadBank("fight.bnk") --创建Listener self.listener_go_=GameObject("listener") self.listener_go_:AddComponent("Transform") self.listener_go_:AddComponent("AudioListener") self.listener_go_:GetComponent("Transform"):set_position(glm.vec3(0,0,0)) -- 创建怪物 self.monster_go_=GameObject("monster") self.monster_go_:AddComponent("Transform"):set_position(glm.vec3(0,0,0)) self.monster_go_:AddComponent("AudioSource") self.monster_go_:GetComponent("AudioSource"):SetEvent("die") self.monster_go_:GetComponent("AudioSource"):set_event_end_callback(function() print("audio monster die end") end) -- 每次播放都改变怪物坐标 self.monster_pos_array_={ glm.vec3(10,0,0), glm.vec3(10,10,0), glm.vec3(0,10,0), glm.vec3(-10,10,0), glm.vec3(-10,0,0) } self.monster_pos_index_=1 self:CreateUI() end -- ...... function GameScene:CreateUI() -- 创建UI相机 GameObject self.go_camera_ui_=GameObject("ui_camera") -- 挂上 Transform 组件 local transform_camera_ui=self.go_camera_ui_:AddComponent("Transform") transform_camera_ui:set_position(glm.vec3(0, 0, 10)) -- 挂上 Camera 组件 local camera_ui=self.go_camera_ui_:AddComponent("UICamera") -- 设置正交相机 camera_ui:SetView(glm.vec3(0, 0, 0), glm.vec3(0, 1, 0)) camera_ui:SetOrthographic(-Screen.width()/2,Screen.width()/2,-Screen.height()/2,Screen.height()/2,-100,100) -- 创建 UIImage self.go_ui_image_=GameObject("image") self.go_ui_image_:AddComponent("Transform"):set_position(glm.vec3(-480, -320, 0)) -- 挂上 UIImage 组件 local ui_image_mod_bag=self.go_ui_image_:AddComponent("UIImage") ui_image_mod_bag:set_texture(Texture2D.LoadFromFile("images/need_head_phone.cpt")) end function GameScene:Update() --print("GameScene:Update") if Input.GetKeyUp(KeyCode.KEY_CODE_SPACE) then print("GameScene:Update KEY_CODE_SPACE") self.monster_go_:GetComponent("Transform"):set_position(self.monster_pos_array_[self.monster_pos_index_]) self.monster_go_:GetComponent("AudioSource"):Play() self.monster_pos_index_=(self.monster_pos_index_%(#self.monster_pos_array_))+1 end end ``` 带上耳机,注意听视频中声音的位置。 <iframe width="800" height="450" src="https://player.bilibili.com/player.html?aid=593102910&bvid=BV16q4y1y742&cid=480734407&page=1" frameborder="0" allowfullscreen> </iframe> B站观看:`https://www.bilibili.com/video/BV16q4y1y742`
<< 1.3 集成Wwise
1.5 Wwise性能分析器介绍 >>
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 猎人开发后记