游戏人生
首页
(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
点赞、收藏、关注
目录
<< 22. Physx物理引擎
22.2 物理材质 >>
## 22.1 Physx实例-小球掉落 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```bash CLion项目文件位于 samples\physx\hello_physx ``` Physx自带了多个实例来介绍API的使用,不过我觉得还是太过复杂,所以本小节用一个最简单的例子:小球掉落,来介绍Physx的初始化、以及可视化工具PVD(PhysX Visual Debugger)的使用。 Physx API文档位于:`physx/documentation/PhysXGuide/Manual/API.html` ![](md/cpp-game-engine-book/imgs/physx/hello_physx/ball.jpg) 小球掉落这个实例,流程如下: ```c++ //file:example/main.cpp line:121 int main() { //~en Init Physx //~zh 初始化Physx InitPhysics(); //~en Create Scene //~zh 创建Scene CreateScene(); //~en Create Plane,add to scene. //~zh 创建地板 CreatePlane(); //~en Create ball //~zh 创建球 CreateBall(); //~en simulate game engine update //~zh 模拟游戏引擎update Simulate(); CleanupPhysics(); return 0; } ``` ### 1. 初始化Physx ```c++ //file:example/main.cpp line:25 //~en Init Physx //~zh 初始化Physx void InitPhysics() { //~en Creates an instance of the foundation class,.only one instance per process. //~zh 创建Foundation实例。 gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback); //~en Connect to pvd(PhysX Visual Debugger). //~zh 连接PVD gPvd = PxCreatePvd(*gFoundation); PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10); gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL); //~en Creates an instance of the physics SDK. //~zh 创建Physx SDK实例 gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd); } ``` 在创建Foundation实例,需要指定内存申请器(gAllocator)与错误回调(gErrorCallback)。 这里是使用了Physx自带的: ```c++ //file:example/main.cpp line:9 PxDefaultAllocator gAllocator; PxDefaultErrorCallback gErrorCallback; ``` #### 1.1 内存申请器 内存申请,每个平台都有不一样的实现,这里看下Windows下的实现。 ```c++ //file:physx\include\extensions\PxDefaultAllocator.h line:89 /** \brief default implementation of the allocator interface required by the SDK */ class PxDefaultAllocator : public PxAllocatorCallback { public: void* allocate(size_t size, const char*, const char*, int) { void* ptr = platformAlignedAlloc(size); PX_ASSERT((reinterpret_cast<size_t>(ptr) & 15)==0); return ptr; } void deallocate(void* ptr) { platformAlignedFree(ptr); } }; ``` #### 1.2 错误回调 `PxDefaultErrorCallback` 定义: ```c++ //file:physx\include\extensions\PxDefaultErrorCallback.h class PxDefaultErrorCallback : public PxErrorCallback { public: PxDefaultErrorCallback(); ~PxDefaultErrorCallback(); virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line); }; ``` `PxDefaultErrorCallback` 实现: ```c++ //file:physx\source\physxextensions\src\ExtDefaultErrorCallback.cpp line:40 PxDefaultErrorCallback::PxDefaultErrorCallback() { } PxDefaultErrorCallback::~PxDefaultErrorCallback() { } void PxDefaultErrorCallback::reportError(PxErrorCode::Enum e, const char* message, const char* file, int line) { const char* errorCode = NULL; switch (e) { case PxErrorCode::eNO_ERROR: errorCode = "no error"; break; case PxErrorCode::eINVALID_PARAMETER: errorCode = "invalid parameter"; break; case PxErrorCode::eINVALID_OPERATION: errorCode = "invalid operation"; break; case PxErrorCode::eOUT_OF_MEMORY: errorCode = "out of memory"; break; case PxErrorCode::eDEBUG_INFO: errorCode = "info"; break; case PxErrorCode::eDEBUG_WARNING: errorCode = "warning"; break; case PxErrorCode::ePERF_WARNING: errorCode = "performance warning"; break; case PxErrorCode::eABORT: errorCode = "abort"; break; case PxErrorCode::eINTERNAL_ERROR: errorCode = "internal error"; break; case PxErrorCode::eMASK_ALL: errorCode = "unknown error"; break; } PX_ASSERT(errorCode); if(errorCode) { char buffer[1024]; sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message); physx::shdfnd::printString(buffer); // in debug builds halt execution for abort codes PX_ASSERT(e != PxErrorCode::eABORT); // in release builds we also want to halt execution // and make sure that the error message is flushed while (e == PxErrorCode::eABORT) { physx::shdfnd::printString(buffer); physx::shdfnd::Thread::sleep(1000); } } } ``` 默认的实现是直接输出错误。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> 一般在项目中要继承`PxErrorCallback`自己实现`reportError`,将Log上传到服务器。 ### 2. 创建Scene ```c++ //file:example/main.cpp line:44 //~en Create Scene //~zh 创建Scene void CreateScene(){ PxSceneDesc sceneDesc(gPhysics->getTolerancesScale()); sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f); gDispatcher = PxDefaultCpuDispatcherCreate(2); sceneDesc.cpuDispatcher = gDispatcher; sceneDesc.filterShader = PxDefaultSimulationFilterShader; gScene = gPhysics->createScene(sceneDesc); PxPvdSceneClient* pvdClient = gScene->getScenePvdClient(); if(pvdClient) { pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true); pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true); pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true); } } ``` Scene是容器,后面创建的地板、小球都要添加到Scene中。 需要对Scene设置一系列参数,例如设置重力为9.81: ```c++ sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f); ``` Physx内部是多线程的,在下面代码里可以设置工作线程数量,这里设置为2. ```c++ gDispatcher = PxDefaultCpuDispatcherCreate(2); ``` 如果设置为0,这样所有的工作都会在调用`PxScene::simulate()`的线程执行。 线程切换是很耗时的,如果项目中的物理模拟运算不多,可能物理模拟运算的耗时还赶不上线程切换的耗时。 那么就可以将线程设置为0,直接在主线程进行物理模拟。 ### 3. 创建地板 ```c++ //file:example/main.cpp line:63 //~en Create Plane,add to scene. //~zh 创建地板 void CreatePlane(){ //~en Create Physx Material. //~zh 创建物理材质 gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f); //~en Create Plane,add to scene. //~zh 创建地板 PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial); gScene->addActor(*groundPlane); } ``` 创建物理材质?看到这个会不会联想到前面讲的模型材质? 所谓材质,就是一系列属性的集合。 模型材质,是渲染这个模型所需要的一系列属性的集合,例如指定贴图、颜色。 物理材质,就是物体用于物理计算所需要的一系列属性的集合,例如摩擦系数、弹性系数,后面再详细介绍。 ### 4. 创建球 ```c++ //file:example/main.cpp line:76 //~en Create ball //~zh 创建球 void CreateBall(){ //~en Create RigidBody,pos is (0,10,0) //~zh 创建刚体,坐标是 (0,10,0) PxRigidDynamic* body = gPhysics->createRigidDynamic(PxTransform(PxVec3(0, 10, 0))); //~en Set rigidbody sharp //~zh 设置刚体形状,一个球。 float radius = 0.5f; PxShape* shape = gPhysics->createShape(PxSphereGeometry(radius), *gMaterial); body->attachShape(*shape); shape->release(); //~en calculate mass,mass = volume * density //~zh 根据体积、密度计算质量 PxRigidBodyExt::updateMassAndInertia(*body, 10.0f); gScene->addActor(*body); } ``` 先创建刚体,再给刚体一个小球形状,就有了小球刚体。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/ball_rigidbody.jpg) 指定球的密度后,就可以用体积*密度算出质量了。 ```diff +PxRigidDynamic表示动态的刚体模拟对象,其继承自PxRigidBody,PxRigidBody继承自PxRigidActor。 -PxRigidStatic 仅表示一个静态物理实体,继承自PxRigidActor。 这两个是物理世界对象的基础节点。 ``` ### 5. 模拟游戏引擎update ```c++ //file:example/main.cpp line:97 //~en simulate game engine update //~zh 模拟游戏引擎update void Simulate(){ static const PxU32 frameCount = 10000; for(PxU32 i=0; i<frameCount; i++) { gScene->simulate(1.0f/60.0f); gScene->fetchResults(true); } } ``` 调用`gScene->simulate(1.0f/60.0f);`开始模拟后,Physx内部多个工作线程就开始计算。 调用`gScene->fetchResults(true);`等待计算结果。 ### 6. 使用PVD查看小球掉落效果 CLion直接运行项目,发现只有控制台输出了`SnippetHelloWorld done.`,说好的球下落没有了。 没办法,作为一个最简单的实例,画面是不可能有的。 那如何去查看小球下落的效果呢,这个时候就要用到PVD(PhysX Visual Debugger)了。 PVD是Physx提供的可视化调试器,先启动PVD,然后再运行项目,连接成功后,项目中的Physx数据就会发送到PVD中。 PVD下载地址:`https://developer.nvidia.com/physx-visual-debugger` 先启动PVD。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/pvd.jpg) 然后启动项目。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/run_project.gif) 在PVD中可以看到小球,小球一瞬间就掉下去了。 为什么没有慢慢往下掉呢,这是因为在实例中是简单的for循环模拟帧,每一帧并没有`1.0f/60.0f`的时间间隔。 PVD中的数据是支持回放的,PVD左上角的控制按钮,分别是回到第一帧,上一帧、倒放、播放、下一帧、最后一帧。 先点击回到第一帧,再点击播放,就可以看到小球掉落的过程。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/pvd_replay.gif) 选中小球,在左侧就会显示小球属性。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/pvd_hierarchy.jpg) 其他的功能就慢慢探索吧。
<< 22. Physx物理引擎
22.2 物理材质 >>
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 猎人开发后记