游戏人生
首页
(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.1 Physx实例-小球掉落
22.3 碰撞检测 >>
## 22.2 物理材质 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` 所谓材质,就是一系列属性的集合。 模型材质,是渲染这个模型所需要的一系列属性的集合,例如指定贴图、颜色。 物理材质,就是物体用于物理计算所需要的一系列属性的集合,例如摩擦系数、弹性系数。 ### 1. 物理材质属性 既然物理材质是用于物理计算的一系列属性集合,那它包括哪些属性呢? 打开Physx的API文档 physx/documentation/PhysXGuide/Manual/API.html,搜索函数名 `createMaterial`,就能找到创建物理材质指定的三个参数的含义。 ![](md/cpp-game-engine-book/imgs/physx/physx_material/api_creatematerial.jpg) | 属性 | 含义 | |---|---| | staticFriction | 静摩擦系数,物体相对静止时与地面的摩擦力系数。 | |dynamicFriction|动摩擦系数,物体相对运动时,与地面的摩擦力系数。| |restitution|弹性系数| 静摩擦力比动摩擦力大一些。 你使出吃奶的力气推箱子,箱子推动之后,就不用那么大力气了。 箱子动起来的那一个临界点,所需的力气是最大的,就说明箱子与地面摩擦力也是最大的。 箱子动起来之后,不用那么大力气了,就说明箱子与地面摩擦力小了。 数值越大,就代表材质的摩擦力越大,就越难移动。 弹性就很好理解了,皮球从高处掉落,如果忽略各种损失,弹性是1,那么就会弹起来回到原位。 如果弹性是0,那么皮球就像掉落进了泥坑。 ### 2. 物理材质属性表现 下面通过2个例子,来分别测试摩擦系数与弹性系数对表现的影响。 #### 2.1 摩擦系数 ```bash CLion项目文件位于 samples\physx\physx_material_friction ``` 情景测试:给小球一个初始速度1.0,对比观察在摩擦系数为0 以及几乎为1的情况下,小球的移动情况。 只是在上一节的基础上对材质稍微修改,这里就不再介绍Physx初始化、创建Scene这些流程了,直接看创建地板、创建小球的相关代码。 ```c++ //file:example/main.cpp line:60 //~en Create Plane,add to scene. //~zh 创建地板 void CreatePlane(){ //~en Create Physx Material. //~zh 创建物理材质 PxMaterial* planeMaterial = gPhysics->createMaterial(98.0f, 100.0f, 0.01f); //~en Create Plane,add to scene. //~zh 创建地板 PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *planeMaterial); gScene->addActor(*groundPlane); } //~en Create ball //~zh 创建球 void CreateBall(){ //~en Create RigidBody,pos is (0,0.5,0) //~zh 创建刚体,坐标是 (0,0.5,0) PxRigidDynamic* rigidDynamic = gPhysics->createRigidDynamic(PxTransform(PxVec3(0, 0.5, 0))); //~en Create Physx Material. //~zh 创建小球的物理材质 PxMaterial* ballMaterial = gPhysics->createMaterial(0.1f, 0.0f, 0.98f); ballMaterial->setFrictionCombineMode(PxCombineMode::eMAX); //~en Set rigid body sharp //~zh 设置刚体形状,一个球。 float radius = 0.5f; PxShape* shape = gPhysics->createShape(PxSphereGeometry(radius), *ballMaterial); rigidDynamic->attachShape(*shape); shape->release(); //~en calculate mass,mass = volume * density //~zh 根据体积、密度计算质量 PxRigidBodyExt::updateMassAndInertia(*rigidDynamic, 10.0f); gScene->addActor(*rigidDynamic); //~en addForce can also make the ball move. //~zh 加上一个力,就可以让小球移动了。注意施加力时,小球必须已经被添加到场景中。 rigidDynamic->addForce(PxVec3(0,0,-20),PxForceMode::eFORCE,true); } ``` 来对比下地板的物理材质与小球的物理材质: ```c++ //~en Create Physx Material. //~zh 创建物理材质 PxMaterial* planeMaterial = gPhysics->createMaterial(98.0f, 100.0f, 0.01f); ``` ```c++ //~en Create Physx Material. //~zh 创建小球的物理材质 PxMaterial* ballMaterial = gPhysics->createMaterial(0.1f, 0.0f, 0.98f); ballMaterial->setFrictionCombineMode(PxCombineMode::eMAX); ``` 地板的物理材质指定了较大的静摩擦力系数与动摩擦力系数。 小球的物理材质指定了几乎为0的摩擦力系数。 小球的物理材质将摩擦力计算模式设置为`PxCombineMode::eMAX`,意思是选取接触的两个物体摩擦力系数较大的一个,那么这里就是选取了地板材质的较大摩擦力系数。 设置好摩擦系数之后,最后给小球施加了一个力,让小球往前滚动。 ```c++ //~en addForce can also make the ball move. //~zh 加上一个力,就可以让小球移动了。注意施加力时,小球必须已经被添加到场景中。 rigidDynamic->addForce(PxVec3(0,0,-20),PxForceMode::eFORCE,true); ``` 摩擦力系数大,就说明阻力大,表现出来就是小球比较难滚动。 打开PVD,然后运行项目后,在PVD中看到效果如下图: ![](md/cpp-game-engine-book/imgs/physx/physx_material/friction_1_be_slow.jpg) 小球在10000帧之后,向前行进了2.487m,然后停止了运动。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> 将小球的物理材质将摩擦力组合模式设置为`PxCombineMode::eMIN`,意思是选取接触的两个物体摩擦力系数较小的一个,那么这里就是选取了小球材质的极小摩擦力系数。 再次运行项目,在PVD中看到效果如下图: ![](md/cpp-game-engine-book/imgs/physx/physx_material/friction_0_forever.jpg) 小球在10000帧之后,向前行进了8.188m,并且仍处于运动中。 #### 2.2 弹性系数 ```bash CLion项目文件位于 samples\physx\physx_material_restitution ``` 情景测试:小球从10m高掉落,对比观察在弹性系数为0 以及几乎为1的情况下,小球的情况。 ![](md/cpp-game-engine-book/imgs/physx/hello_physx/ball.jpg) 直接看创建地板、创建小球的相关代码。 ```c++ //file:example/main.cpp line:60 //~en Create Plane,add to scene. //~zh 创建地板 void CreatePlane(){ //~en Create Physx Material. //~zh 创建物理材质 PxMaterial* planeMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.01f); //~en Create Plane,add to scene. //~zh 创建地板 PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *planeMaterial); gScene->addActor(*groundPlane); } //~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 Create Physx Material. //~zh 创建小球的物理材质 PxMaterial* ballMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.98f); //~en Set ball material restitution combine mode. When ball hit the floor, choose the larger, smaller, or average of the two. //~zh 设置小球材质的弹性系数计算模式,小球与地板碰撞时,弹性系数是取两者大的、小的、还是平均。 ballMaterial->setRestitutionCombineMode(PxCombineMode::eMAX); // ballMaterial->setRestitutionCombineMode(PxCombineMode::eAVERAGE); // ballMaterial->setRestitutionCombineMode(PxCombineMode::eMIN); //~en Set rigid body sharp //~zh 设置刚体形状,一个球。 float radius = 0.5f; PxShape* shape = gPhysics->createShape(PxSphereGeometry(radius), *ballMaterial); body->attachShape(*shape); shape->release(); //~en calculate mass,mass = volume * density //~zh 根据体积、密度计算质量 PxRigidBodyExt::updateMassAndInertia(*body, 10.0f); gScene->addActor(*body); } ``` 对比地板的物理材质与小球的物理材质: ```c++ //~en Create Physx Material. //~zh 创建物理材质 PxMaterial* planeMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.01f); ``` ```c++ //~en Create Physx Material. //~zh 创建小球的物理材质 PxMaterial* ballMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.98f); //~en Set ball material restitution combine mode. When ball hit the floor, choose the larger, smaller, or average of the two. //~zh 设置小球材质的弹性系数计算模式,小球与地板碰撞时,弹性系数是取两者大的、小的、还是平均。 ballMaterial->setRestitutionCombineMode(PxCombineMode::eMAX); ``` 地板的物理材质指定了几乎为0的弹性系数。 小球的物理材质指定了几乎为1的弹性系数。 小球的物理材质将弹性系数组合模式设置为`PxCombineMode::eMAX`,意思是选取接触的两个物体弹性系数较大的一个,那么这里就是选取了小球材质的较大弹性系数。 弹性系数越大,表现出来就是小球下落后能弹回得越高。 打开PVD,然后运行项目后,在PVD中看到效果如下图,小球几乎能弹回到原来的位置: ![](md/cpp-game-engine-book/imgs/physx/physx_material/restitution_max_0_0.98.gif) 将小球的物理材质将摩擦力组合模式设置为`PxCombineMode::eMIN`,意思是选取接触的两个物体弹性系数较小的一个,那么这里就是选取了地板材质的几乎为0的弹性系数。 再次运行项目,在PVD中看到效果如下图,小球下落后就不动了,像掉到了泥坑里: ![](md/cpp-game-engine-book/imgs/physx/physx_material/restitution_min_0_0.98.gif) ### 3. 物理引擎的误差 上面测试小球材质的弹性系数时,如果要百分百弹回到原来的位置,那是不是只要将弹性系数设置为1.0就可以了呢? 修改好代码后,在PVD中看到效果如下图: ![](md/cpp-game-engine-book/imgs/physx/physx_material/restitution_10.gif) 可以看到小球越弹越高了,这是怎么回事? 在谷歌搜索几乎没有找到有效信息,只能请教公司大佬,大佬的意思是物理引擎是一定存在误差的,这里既有浮点型精度问题,也有其他的一些问题,随着时间的增加,误差会逐渐放大。如果要让小球完美回到原位,只能将Distitution设置得稍微小一点,然后在快到顶端的时候做些拟合,例如给它加一些力,或者直接设置位置。 不过我想到Unity是用Physx做物理引擎的,Unity的物理材质属性和Physx是一一对应,只是将Physx Restitution改成了 Bounciness。 所以拿Unity也测试了一次,发现表现是一致的。 ![](md/cpp-game-engine-book/imgs/physx/physx_material/unity_restitution_1.gif) 在谷歌搜索`unity bounciness 1.0`就能找到一些信息。 ```bash https://forum.unity.com/threads/bounciness-1-0-conservation-of-energy-doesnt-work.143472/ ``` 这里Unity的技术支持给到的解释和解决方案和公司大佬说的一致。
<< 22.1 Physx实例-小球掉落
22.3 碰撞检测 >>
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 猎人开发后记