游戏人生
首页
(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
点赞、收藏、关注
目录
<< 5.5 绘制带贴图的立方体盒子
5.7 图片压缩工具 >>
## 5.6 压缩纹理 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```c CLion项目文件位于 samples\texture\draw_cube_texture_compress ``` 上一节解析了 `urban.jpg` 这个图片,从中拿到RGB数据,上传到GPU,进行渲染。 上传RGB数据到GPU,使用了下面的代码: ```c++ //3. 将图片rgb数据上传到GPU; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture2d->width_, texture2d->height_, 0, texture2d->gl_texture_format_, GL_UNSIGNED_BYTE, data); ``` 接口定义如下: ```c++ /** * @brief 将图片数据上传到GPU; * @param target 目标纹理,GL_TEXTURE_2D(2D纹理) * @param level 当图片数据是包含多个mipmap层级时,指定使用mipmap层级。 * @param internalformat 图片数据上传到GPU后,在显存中保存为哪种格式? * @param width * @param height * @param border * @param format 上传的图片数据格式,RGB、RGBA、Alpha等 * @param type 图片数据变量格式,一般都是GL_UNSIGNED_BYTE(0-255范围) * @param pixels 图片数据 * @return */ void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); ``` 注意 `internalformat` 这个参数。 图片数据上传到到GPU后,可以选择保存的格式。 而我们这一章的主题是`压缩纹理`,那么我要讲的就是,可以保存为压缩格式。 ### 1. 为什么使用压缩纹理? 为什么图片导入Unity之后,默认会设置为压缩格式? 在`glTexImage2D`这个接口里面,设置图片数据保存为压缩格式后,会有什么好处? 答案就是:<font color=blue>节省显存</font>。 如今的3A大作,各种4K贴图、超高精度模型,一个场景数据量几G,这些数据都是要上传到显存的,为了让游戏适配更多的硬件,开发者们也是各显神通,压缩纹理就是OpenGL官方提供的一种手段。 ### 2. 使用压缩纹理 OpenGL支持的纹理数据格式如下: | 纹理格式 | 压缩纹理格式 | |:---|:---| |GL_ALPHA|GL_COMPRESSED_ALPHA| |GL_LUMINANCE|GL_COMPRESSED_LUMINANCE| |GL_LUMINANCE_ALPHA|GL_COMPRESSED_LUMINANCE_ALPHA| |GL_RGB|GL_COMPRESSED_RGB| |GL_RGBA|GL_COMPRESSED_RGBA| |GL_INTENSITY|GL_COMPRESSED_INTENSITY| 之前`glTexImage2D`这个接口的 `internalformat` 参数值是`GL_RGB`,现在只要设置为对应的压缩纹理格式`GL_COMPRESSED_RGB`即可。 ```c++ //3. 将图片rgb数据进行压缩上传到GPU。 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, texture2d->width_, texture2d->height_, 0, texture2d->gl_texture_format_, GL_UNSIGNED_BYTE, data); ``` ### 3. 查看压缩纹理效果 代码编译运行后,正常绘制了立方体,但是怎么样确认压缩纹理的效果呢,就是说怎么样确认显存占用降低? 这里借助GPU状态工具 - `GPU-Z` 来查看实时显存。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> 使用未压缩纹理,`glTexImage2D`接口调用前后显存对比如下: ![](md/cpp-game-engine-book/imgs/texture_make_beautiful/draw_cube_texture_compress/rgb_memory.gif) 从52m 变动到 116m,使用了约 64m 显存。 使用压缩纹理,接口调用前后显存对比如下: ![](md/cpp-game-engine-book/imgs/texture_make_beautiful/draw_cube_texture_compress/rgb_compress_memory.gif) 从52m 变动到 60m,使用了约 8m 显存。 效果很明显,压缩纹理后,占用的显存是原来的 1/6 左右。 对比Unity中压缩后的效果,差异不大。 ![](md/cpp-game-engine-book/imgs/texture_make_beautiful/draw_cube_texture_compress/unity_compress_size.jpg) ### 4. 问题与优化 启动时有一段时间的白屏,断点调试发现`stbi_load` 和 `glTexImage2D`耗时较长,这里引入`stopwatch`工具类来进行测量。 ```c++ Texture2D* Texture2D::LoadFromFile(std::string& image_file_path) { ...... StopWatch stopwatch; stopwatch.start(); unsigned char* data = stbi_load(image_file_path.c_str(), &(texture2d->width_), &(texture2d->height_), &channels_in_file, 0); stopwatch.stop(); std::int64_t decompress_jpg_cost = stopwatch.milliseconds(); ...... stopwatch.restart(); //3. 将图片rgb数据进行压缩上传到GPU。 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, texture2d->width_, texture2d->height_, 0, texture2d->gl_texture_format_, GL_UNSIGNED_BYTE, data); stopwatch.stop(); std::int64_t upload_and_compress_cost = stopwatch.milliseconds(); ...... } ``` 耗时结果如下: ![](md/cpp-game-engine-book/imgs/texture_make_beautiful/draw_cube_texture_compress/jpg_cost.jpg) 从硬盘加载jpg并解析得到RGB数据:1571 ms 压缩RGB数据上传到GPU:960 ms 这只是一张4096的图片,就花费了2.5s的时间,我们必须想办法优化。 制定优化方案之前,先理清楚为什么这么慢,主要是3个原因: 1. 解析jpg慢:jpg是一种压缩图片文件,需要解压才可以得到未压缩的RGB数据,解压是很慢的一个过程。 2. 压缩慢:对RGB数据进行压缩为GPU直接支持的格式,压缩需要耗费时间。 3. 上传慢:4096的图片,即使压缩后,上传要耗费一定时间。 对应的解决办法就是:<font color=blue>使用GPU支持的压缩纹理数据格式</font>。 具体做法就是:将压缩好的纹理数据,保存到硬盘作为图片文件。 带来的好处是: 1. 无需解析,直接上传GPU。 2. 数据已经压缩,无需再次压缩。 3. 数据已经压缩,上传数据量小。 OpenGL提供了接口`glGetCompressedTexImage`,将压缩好的纹理数据,从显存下载到内存,下一节将制作一个工具,对`.jpg`、`.png` 图片进行批量处理。
<< 5.5 绘制带贴图的立方体盒子
5.7 图片压缩工具 >>
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 猎人开发后记