一、原始图像数据
- 像素包装
图像的存储空间 = 图像的宽度 * 图像的高度 * 每个像素的字节数
像素数据的数据类型
GL_UNSIGNED_BYTE : 每种颜色分量都是一个8位无符号整数。
二、常用函数
2.1 载入纹理
// 2D
void glTexImage2D(GLenum target, GLint level,GLint internalformat,
GLsizei width,GLsizei height , GLint border ,GLenum ,GLenum type,void * data);
// 3D
/*
* target:`GL_TEXTURE_1D`、`GL_TEXTURE_2D`、`GL_TEXTURE_3D`。
* Level:指定所加载的mip贴图层次。一般我们都把这个参数设置为0。
* internalformat:每个纹理单元中存储多少颜色成分。
* width、height、depth参数:指加载纹理的宽度、高度、深度。但这些值必须是
2的整数次方。(这是因为OpenGL 旧版本上的遗留下的要求。当然现在已经可以支持不是
2的整数次方。但是开发者们还是习惯以2的整数次方去设置这些参数。)
* border参数:允许为纹理贴图指定一个边界宽度。
* format、type、data参数:与glDrawPixels 函数对应的参数相同
*/
void glTexImage3D(GLenum target, GLint level,GLint internalformat,
GLsizei width,GLsizei height,GLsizei depth , GLint border ,GLenum ,GLenum type,void * data);
2.2 使用颜色缓存区加载数据,形成新的纹理以供使用
void glCopyTexImage2D(GLenum target, GLint level,GLint internalformat, GLint x,GLint y,GLsizei width, GLint border ,)
/*
* x,y 在颜色缓存区中指定了开始读取纹理数据的位置,缓存区里的数据,是源缓存区通过glReadBuffer设置的(其中需要注意的是,不存在glCopyTexImage3D,
原因是我们无法从2D颜色缓存区中获取体积数据。)
*/
void glCopyTexImage2D(GLenum target, GLint level,GLint internalformat, GLint x,GLint y,
GLsizei width,GLsizei height , GLint border ,)
2.3 纹理对象
- 使用函数分配纹理对象
/*
* 指定纹理对象的数量和指针(指针指向一个无符号整形数组,由纹理对象标识符填充)
*/
void glGenTextures(GLsizei n,GLunit * textures);
- 绑定纹理状态
/*
* target: GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
* texture: 需要绑定的纹理对象
*/
void glBindTexture(GLenum target,GLunit texture);
- 删除纹理对象
/*
* 纹理对象以及纹理对象指针(指针指向一个无符号整型数组,由纹理对象标识符填充)
*/
void glDeleteTextures(GLsizei n,GLunit *textures);
- 测试纹理对象是否有效
// 如果Texture是一个已经分配空间的纹理对象,那么这个函数会返回GL_TURE,否则会返回GL_FALSE。
GLboolean glIStexture(GLunit texture);
2.4 设置纹理参数
// param1-> target :指定这些参数将要应用在哪个纹理模式上,如GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
// param2->pname:指定需要设置的哪个纹理参数
// param3-> param: 设定的纹理参数的值
glTexParameterf(GLenum target,GLenum pname,GLFloat param);
glTexParameteri(GLenum target,GLenum pname,GLint param);
glTexParameterfv(GLenum target,GLenum pname,GLFloat param);
glTexParameteriv(GLenum target,GLenum pname,GLint * param);
2.5 设置过滤方式
- 有两种过滤方式,邻近过滤——GL_NEAREST(最近采样点过滤),线性过滤——GL_LINEAR
-
邻近过滤:纹理坐标位于哪个单元,则选该单元作为该颜色片段的颜色值;这样虽然简单的解决了纹理单元和像素一一对应的关系,但也会导致贴图后会出现像素斑驳的想象。
邻近过滤 -
线性过滤:它会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个纹理像素的颜色对最终的样本颜色的贡献越大。
线性过滤
两种过滤方式对比
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// 纹理放大时,使用线性过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
邻近过滤 VS 线性过滤
2.6 设置环绕方式
环绕方式 | 说明 |
---|---|
GL_REPEAT | 对纹理的默认行为。重复纹理图像。 |
GL_MIRRORED_REPEAT | 和GL_REPEAT一样,但每次重复图片是镜像放置的。 |
GL_CLAMP_TO_EDGE | 纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。 |
GL_CLAMP_TO_BORDER | 超出的坐标为用户指定的边缘颜色。 |
/*
* para1:GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
* para2:GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T,GL_TEXTURE_WRAP_R,对应s,t,r坐标(也是x,y,z)
* para3:GL_MIRRORED_REPEAT-> OpenGL 在纹理坐标超过1.0的方向上对纹理进行重复
GL_CLAMP-> 所需纹理单元取自纹理边界或TEXTURE_BORDER_COLOR.
GL_CLAMP_TO_EDGE-> 环绕模式强制对范围之外的纹理坐标沿着合法的边界纹理单元的最后一行或最后一列进行采样
GL_CLAMP_TO_BORDER-> 在纹理坐标为0.0至1.0范围之外的只使用边界纹理单元,边界纹理单元是作为环绕基本图像的额外行与列,并且和基本纹理图像同时加载。
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
当纹理坐标超出默认范围时,每个选项都有不同的视觉效果输出。以下贴出四种方式示例:
四种环绕方式
2.7 纹理映射关系
纹理坐标在x和y轴上,范围为0到1之间(注意我们使用的是2D纹理图像)。使用纹理坐标获取纹理颜色叫做采样(Sampling)。纹理坐标起始于(0, 0),也就是纹理图片的左下角,终始于(1, 1),即纹理图片的右上角。下面将展示我们是如何把纹理坐标映射到三角形上的。
通过设置对应的纹理坐标,将其映射至三角形的描绘上
GLfloat texCoords[] = {
0.0f, 0.0f, // 左下角
1.0f, 0.0f, // 右下角
0.5f, 1.0f // 上中
};
我们为三角形指定了3个纹理坐标点。我们希望三角形的左下角对应纹理的左下角,因此我们把三角形左下角顶点的纹理坐标设置为(0, 0);三角形的上顶点对应于图片的上中位置所以我们把它的纹理坐标设置为(0.5, 1.0);同理右下方的顶点设置为(1, 0)。我们只要给顶点着色器传递这三个纹理坐标就行了,接下来它们会被传片段着色器中,它会为每个片段进行纹理坐标的插值。
纹理坐标引用链接(翻译): https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/06%20Textures/
英文: https://learnopengl.com/Getting-started/Textures
网友评论