游戏人生
首页
(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.4 使用stb_image解析图片
5.6 压缩纹理 >>
## 5.5 绘制带贴图的立方体盒子 ```text 「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book ``` ```c CLion项目文件位于 samples\texture\draw_cube_texture ``` 上一节已经解析了图片,得到RGB数据,这一节将数据上传到显卡并渲染。 ### 1. 上传RGB数据到显卡 在 `texture2d.h` 中,添加成员变量`gl_texture_id_`存储GPU创建纹理的唯一ID。 ```c++ GLuint gl_texture_id_;//纹理ID ``` 解析图片成功后,将图片RGB数据上传到GPU。 ```c++ Texture2D* Texture2D::LoadFromFile(std::string& image_file_path) { Texture2D* texture2d=new Texture2D(); stbi_set_flip_vertically_on_load(true);//翻转图片,解析出来的图片数据从左下角开始,这是因为OpenGL的纹理坐标起始点为左下角。 int channels_in_file;//通道数 unsigned char* data = stbi_load(image_file_path.c_str(), &(texture2d->width_), &(texture2d->height_), &channels_in_file, 0); if (data!= nullptr) { //根据颜色通道数,判断颜色格式。 ...... } //1. 通知显卡创建纹理对象,返回句柄; glGenTextures(1, &(texture2d->gl_texture_id_)); //2. 将纹理绑定到特定纹理目标; glBindTexture(GL_TEXTURE_2D, texture2d->gl_texture_id_); //3. 将图片rgb数据上传到GPU; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture2d->width_, texture2d->height_, 0, texture2d->gl_texture_format_, GL_UNSIGNED_BYTE, data); //4. 指定放大,缩小滤波方式,线性滤波,即放大缩小的插值方式; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //释放图片文件内存 stbi_image_free(data); return texture2d; } ``` 这样,RGB数据就上传到显卡中了。 数据上传后,返回纹理句柄供后续使用。 下面来看看在Shader中如何从纹理上获取颜色数据。 ### 2. Shader中使用纹理 在片段Shader中使用,GLSL提供函数 `texture2D` ,在纹理的指定坐标上,取出颜色值。 ```c vec4 texture2D(sampler2D sampler, vec2 coord, float bias) ``` 参数sampler就是纹理数据。 参数coord就是UV坐标。 下面就是完整的片段Shader。 ```glsl #version 110 uniform sampler2D u_diffuse_texture; varying vec4 v_color; varying vec2 v_uv; void main() { gl_FragColor = texture2D(u_diffuse_texture,v_uv); } ``` 主要是调用`texture2D`函数,从纹理 `u_diffuse_texture` 中,以 `v_uv` 为UV坐标,取出颜色值,赋值给 `gl_FragColor`作为颜色输出。 UV坐标,在 `5.1 颜色和贴图` 这一节简单介绍过,注意看上面的片段Shader代码: ```glsl varying vec2 v_uv; ``` 变量`v_uv`被 `varying` 修饰,说明UV坐标是从顶点Shader传递过来的,数据经过插值。 顶点Shader代码如下: ```glsl #version 110 uniform mat4 u_mvp; attribute vec3 a_pos; attribute vec4 a_color; attribute vec2 a_uv; varying vec4 v_color; varying vec2 v_uv; void main() { gl_Position = u_mvp * vec4(a_pos, 1.0); v_color = a_color; v_uv = a_uv; } ``` 介绍完了纹理的使用过程,下面就传入UV坐标和纹理到Shader中进行渲染。<a id="antiCollectorAdTxt" href="https://github.com/ThisisGame/cpp-game-engine-book">「游戏引擎 浅入浅出」是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book</a> ### 3. 上传UV坐标 UV坐标和顶点坐标也是一一对应,且取值范围是[0,1]。 立方体有6个面,每个面2个三角形,对应UV坐标数据如下: ```c++ static const glm::vec2 kUvs[36] = { //Front glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //back glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //left glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //right glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //up glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //down glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), }; ``` 然后获取顶点Shader中的UV变量: ```c++ a_uv_location = glGetAttribLocation(program, "a_uv"); ``` 启用顶点Shader属性(a_uv): ```c++ glEnableVertexAttribArray(a_uv_location); ``` 联顶点UV数据: ```c++ //关联顶点UV数据 glVertexAttribPointer(a_uv_location, 2, GL_FLOAT, false, sizeof(glm::vec2), kUvs); ``` ### 4.指定纹理渲染 上面已经上传了图片RGB到GPU中,并且生成了纹理,拿到了纹理句柄。但是仍然需要将纹理句柄传入到Shader,下面就来做这个事情。 ```c++ //指定GPU程序(就是指定顶点着色器、片段着色器) glUseProgram(program); { ...... //贴图设置 //激活纹理单元0 glActiveTexture(GL_TEXTURE0); //将加载的图片纹理句柄,绑定到纹理单元0的Texture2D上。 glBindTexture(GL_TEXTURE_2D,texture2d->gl_texture_id_); //设置Shader程序从纹理单元0读取颜色数据 glUniform1i(u_diffuse_texture_location,0); //void glDrawArrays(GLenum mode,GLint first,GLsizei count); glDrawArrays(GL_TRIANGLES, 0, 6*6);//表示从第0个顶点开始画,总共画6个面,每个面6个顶点。 } ``` 代码很简单,不过逻辑很绕,这里需要解释一下。 我们并不直接将纹理句柄指定给片段Shader,而是通过`纹理单元`进行中转。 ```c 纹理单元可以看做是纹理句柄的容器。 ``` 首先激活纹理单元,然后将纹理句柄绑定到纹理单元,然后将纹理单元指定给片段Shader。 最终运行效果: ![](md/cpp-game-engine-book/imgs/texture_make_beautiful/draw_cube_texture/draw_cube_urban.gif)
<< 5.4 使用stb_image解析图片
5.6 压缩纹理 >>
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 猎人开发后记