- 为何要有纹理?
- 纹理坐标
- 加载图片数据到内存
- 选用现成库
- 使用 stb_image.h
- 删除加载的图片数据
- 纹理对象
- 创建纹理对象
- 设置为当前操作的纹理对象
- 删除纹理对象
- 设置纹理对象内部格式以及传入图像数据
- Base Internal Format(内部格式)
- Sized Internal Format
- 也可以从纹理对象中读取数据到内存
- 纹理单元
- 先激活纹理单元
- 采样器
- 应用层程序添加顶点属性
- 运行效果
- 完整源码
- 总结
- References
本人才疏学浅,如有什么错误,望不吝指出。
上一篇:LearnGL - 04.2 - 封装 ShaderProgram 类,对 Shader、Program 封装了类,便于后续使用。
这一篇:继续我们的 OpenGL 学习主线内容:纹理(Texture)。纹理的内容挺多的,这里只讲到部分的内容。
为何要有纹理?想让我们的几何体(模型)看起来更丰富,除了之前我们说过的 添加顶点(由 三角形 到 四边形,再多一些就甚至可以是圆形,甚至是各种几何体,只要顶点数量足够多)、然后给顶点添加颜色,最终都控制如何显示 成最后的屏幕像素,让它看起来更丰富的内容。
一些色彩丰富的物体,如一些画家画的抽象画,什么鬼颜色都有,如果我们只用添加顶点的方式,让每一块相同的颜色,都弄一个几何体(一堆顶点),并添加顶点颜色来表示的话,那估计建模的同学会疯掉。
所以聪明的人类、聪明的图形先辈们想到了一个方法:纹理。
纹理这玩意儿,有点像我们在一个气球上画一些图像,或是写一些字,然后我们将气球吹鼓。
再将气球捏来捏去的,改变它的形状,你会发现气球上的图案都很好的映射在你画在对应位置上的气球表面位置上;最后你将气球泄气会原型后,你会发现画在气球上的图像内容都还原样的保留着(除非你使劲儿地把画上去的颜料戳没了。-_-!!!)。
所以我们的 纹理 也是类型这么个映射。这个方法可就很好的替代了上面添加N个无穷无尽的表面顶点来丰富画面了。工作量上可是省了 N 多的量。建模同学是个幸运儿,都没经历这么多痛的假设工作量,都给图形先辈们提前想到并解决了。
纹理 的整体系统的思路很简单,先提供一些保存着图像内容的 图片(纹理贴图 texture map),这些图片都有一些纹理坐标,就想我们画的一个二维的笛卡尔坐标一样,也有个坐标。然后在顶点属性上添加一个映射在纹理采样的坐标,这样不管我的顶点变化到哪去,我都让该顶点映射纹理坐标的位置不变。顶点的位置变化能引起图像映射的内容伸缩,但这正是我们想要的效果,就想上面提到的气球的例子一样。而上面的顶点坐标中映射了纹理坐标,我们通常叫:纹理映射(Texture-Mapping)。
纹理坐标前面简单的简述了纹理的概念,也提到了 纹理坐标 的概念。
纹理系统中的 纹理贴图(texture map) 就是张图片,而这张 图片的坐标 通常是下面的方式:
但是我们的 纹理坐标 可不一样:(0,0)在左下角,即:Y轴的增量方向是朝上的。
有好几种方法
- 一种是使用:http://www.opengl-redbook.com,(红宝书)中的源码:
vglLoadImage
、vglUnloadIImage
、vglLoadTexture
、等方法。(如果要全面一些的加载也可以使用这个) - 一种是:SOIL(Simple OpenGL Image Library,简要的 OpenGL 图像库),
unsinged char* image = SIO_load_image("filename.ext", &width, &height, 0 SOIL_LOAD_RGB);
(为了做学习用,可以使用这个) - 一种是:stb_image.h。(这个库使用比较简单,我是推荐使用这个)
我使用的是也 stb_image.h 的加载方式,使用方式可以参考:stb_image.h,除了参考文中说明的使用方式,大家也可以查查此头文件中的前面的注释,也有很详细的英文说明。
将此文件放在我们的 include path(包含目录)
在源码中包含此头文件之前,先要定义宏:
#define STB_IMAGE_IMPLEMENTATION
就像这样:
#define STB_IMAGE_IMPLEMENTATION
#include"stb_image.h"
加载图片:
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
使用 stb_image.h
上面确定使用了 stb_image.h
,下面我们列出我们使用到的加载方式。
要将图片数据加载到纹理中,首先我们先将图片数据加载到内存
// loading texture here...
// 加载纹理需要用的图片数据
char img_path[MAX_PATH];
g_GetPicturePathCallback(img_path, "my_tex.png"); // 获取图片目录
int img_w, img_h, img_channels;
stbi_set_flip_vertically_on_load(1); // 也可以在加载前设置加载时翻转的变量
unsigned char* img_data = stbi_load(img_path, &img_w, &img_h, &img_channels, 4); // 加载图片数据,返回确定宽、高、通道数量、每个分量要多少字节
if (img_data == NULL) { // 如果加载图片失败
std::cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?