游戏人生
首页
(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
点赞、收藏、关注
目录
<< 6. 索引与缓冲区对象
6.2 缓冲区对象 >>
## 6.1 顶点索引 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` 回顾`3.2 画个正方形` 这一章的实例,绘制一个正方形,需要上传6个顶点数据到GPU。 但是我们都知道,实际上只有4个顶点数据。只是为了凑成2个三角形,将这4个顶点分为了 3 3 两份。 重复的顶点不仅增加了上传到GPU的数据量,也增加了GPU顶点着色器的执行次数(每个顶点执行一次)。 OpenGL提供了新的机制 - `顶点索引`,来进行优化。 ### 1. 何为顶点索引 从实例代码中也可以看到,顶点坐标数据是一个数组,那么顶点索引就是这个数组的index。 以正方形的顶点坐标数据为例: ```c++ static const glm::vec3 kPositions[6] = { //第一个三角形 { -1.0f, -1.0f, 0.0f},//左下 { 1.0f, -1.0f, 0.0f},//右下 { 1.0f, 1.0f, 0.0f},//右上 //第二个三角形 { 1.0f, 1.0f, 0.0f},//右上 { -1.0f, 1.0f, 0.0f},//左上 { -1.0f, -1.0f, 0.0f}//左下 }; ``` 去掉重复,实际上只有4个顶点: ```c++ static const glm::vec3 kPositions[4] = { { -1.0f, -1.0f, 0.0f},//左下 { 1.0f, -1.0f, 0.0f},//右下 { 1.0f, 1.0f, 0.0f},//右上 { -1.0f, 1.0f, 0.0f},//左上 }; ``` 这4个顶点,要怎么组成2个三角形呢? 去重后顶点坐标数据不可以重复,但是可以新建一个数组,存储重复的顶点索引。 ```c++ static const glm::vec3 indices[6] = { //第一个三角形 0,1,2, //第二个三角形 2,3,1 }; ``` 借助顶点索引数组,间接地组成了2个三角形。 ### 2. 何为顶点? ```c 本段落CLion项目文件位于 samples\vertex_index_and_buffer\vertex ``` 上面说了,将顶点坐标去重,然后新建数组存储下标,那么顶点颜色和UV坐标怎么处理呢? 这里我们要明确一个概念 -- <font color=blue>顶点是什么?</font> 在之前的例子,我用`glVertexAttribPointer`来设置顶点属性,如下面的代码将顶点坐标数组与 顶点shader中的变量`vpos_location`关联。 ```c++ glVertexAttribPointer(vpos_location, 3, GL_FLOAT, false, sizeof(glm::vec3), kPositions); ``` 具体绘制多少个顶点,是在`glDrawArrays`指定的,如下面代码绘制一个立方体,就有6*6=36个顶点。 ```c++ glDrawArrays(GL_TRIANGLES, 0, 6*6);//表示从第0个顶点开始画,总共画6个面,每个面6个顶点。 ``` 在`4.3 顶点着色器` 这小节里说过,顶点着色器是每个顶点执行一次。 其实就是说`glDrawArrays`指定了多少个顶点,就执行多少次。 那么每次执行,就以当前顶点序号为下标,从`glVertexAttribPointer`设置的顶点属性去拿数据,设置到顶点shader的变量`vpos_location`中。 那么顶点属性的数据,这个数组,长度一定是要等于`glDrawArrays`指定的顶点数的,不然就会取不到数据。 按照这个逻辑,我将所有用`glVertexAttribPointer`设置的顶点属性,相同下标的,称之为一个顶点。  如上图,虚线框中的为一个顶点。 <font color=blue>一般来说,一个顶点,包含了顶点坐标、顶点颜色、UV坐标这三个数据。 三者任意之一不同,那么就是2个不同的顶点。</font> 所以使用顶点索引需要进行去重,是去掉三者完全相同的顶点。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> 为了更深入理解顶点概念,对`vertex_data.h`进行修改,引入`struct Vertex`,并将之前的顶点坐标(kPositions)、顶点颜色(kColors)、UV坐标(kUvs)这三个数据合并为顶点(kVertexs)。 ```c++ //顶点 struct Vertex { glm::vec3 pos_; glm::vec4 color_; glm::vec2 uv_; }; static const Vertex kVertexs[36] ={ //Front glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(0.0f, 0.0f), glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(1.0f, 0.0f), glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(1.0f, 1.0f), glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(0.0f, 0.0f), glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(1.0f, 1.0f), glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(0.0f, 1.0f), //back glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec4(1.0f,1.0f,1.0f,1.0f), glm::vec2(0.0f, 0.0f), ...... }; ``` 然后在将顶点数据与顶点Shader属性进行关联时,需要加上指针偏移,代码如下: ```c++ //main.cpp //启用顶点Shader属性(a_pos),指定与顶点坐标数据进行关联 glEnableVertexAttribArray(vpos_location); glVertexAttribPointer(vpos_location, 3, GL_FLOAT, false, sizeof(Vertex), kVertexs); //启用顶点Shader属性(a_color),指定与顶点颜色数据进行关联 glEnableVertexAttribArray(vcol_location); glVertexAttribPointer(vcol_location, 4, GL_FLOAT, false, sizeof(Vertex), ((float*)kVertexs) + 3); //启用顶点Shader属性(a_uv),指定与顶点UV数据进行关联 glEnableVertexAttribArray(a_uv_location); glVertexAttribPointer(a_uv_location, 2, GL_FLOAT, false, sizeof(Vertex), ((float*)kVertexs) + 3 + 4); ``` 代码修改后,模糊掉了顶点坐标、顶点颜色、UV坐标这三个数据,面对的就是顶点这个整体。 ### 3. 使用顶点索引绘制立方体 下面就在上一段落的实例项目基础之上,使用顶点索引绘制立方体。 ```c CLion项目文件位于 samples\vertex_index_and_buffer\indices ``` #### 3.1 去除重复顶点 上一段落的实例项目,存有36个顶点在`kVertexs[36]`中,首先编写代码将顶点数据去重: ```c++ //vertex_data.h //去重的顶点Vector static vector<Vertex> kVertexRemoveDumplicateVector; //顶点索引Vector static vector<unsigned short> kVertexIndexVector; //顶点去重 static void VertexRemoveDumplicate(){ for (int i = 0; i < 36; ++i) { const Vertex& vertex=kVertexs[i]; //判断顶点是否存在 ...... } } ``` 断点调试,发现顶点去重后只剩下16个,节省了一大半内存。  后续渲染就使用去重后的顶点数据(kVertexRemoveDumplicateVector) 和 顶点索引(kVertexIndexVector)。 #### 3.2 使用顶点索引绘制 首先将去重后的顶点数据(kVertexRemoveDumplicateVector)与Shader属性进行绑定: ```c++ //启用顶点Shader属性(a_pos),指定与顶点坐标数据进行关联 glVertexAttribPointer(vpos_location, 3, GL_FLOAT, false, sizeof(Vertex), (float*)(&kVertexRemoveDumplicateVector[0])); //启用顶点Shader属性(a_color),指定与顶点颜色数据进行关联 glVertexAttribPointer(vcol_location, 4, GL_FLOAT, false, sizeof(Vertex), ((float*)(&kVertexRemoveDumplicateVector[0]) + 3)); //顶启用顶点Shader属性(a_uv),指定与点UV数据进行关联 glVertexAttribPointer(a_uv_location, 2, GL_FLOAT, false, sizeof(Vertex), ((float*)(&kVertexRemoveDumplicateVector[0]) + 3 + 4)); ``` 然后使用顶点索引(kVertexIndexVector)进行绘制,需要引入新的API - `glDrawElements`。 ```c++ void glDrawElements(GLenum mode,GLsizei count,GLenum type,const void * indices); 参数解析: mode 几何图元类型,可选 GL_POINT(点)、GL_LINE(线)、GL_TRIANGLES(三角形) count 几何图元数量 type 索引数据类型 indices 索引数组 ``` 将原来的代码修改为: ```c++ //glDrawArrays(GL_TRIANGLES, 0, 6*6);//表示从第0个顶点开始画,总共画6个面,每个面6个顶点。 glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_SHORT,(float*)(&kVertexIndexVector[0]));//使用顶点索引进行绘制。 ``` 再次编译运行,结果正常: 
<< 6. 索引与缓冲区对象
6.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 猎人开发后记