第十六节—纹理常用API

2020-09-01  本文已影响0人  L_Ares

本文为L_Ares个人写作,包括图片皆为个人亲自操作,以任何形式转载请表明原文出处。

之前的学习中绘制图形全部都是使用的颜色来渲染的,但是实际的需求中很多都是需要图片来进行渲染,本节的纹理就是可以利用图片将图形的外观发生改变。

首先,我们学习拿一张图片作为纹理。先了解一张图片的存储空间是怎么计算的:

一张图片的存储空间 = 图片的宽 * 图片的高 * 每个像素的字节数

OpenGL中纹理图片需要.tga格式的文件,.tga格式的文件存储方式是1个字节1个字节的存储,这样更节约存储空间。

下面开始介绍一些OpenGL中常用的纹理相关的函数。

1. 改变像素存储的方式

void glPixelStorei(GLenum pname,GLint param);

2. 回复像素存储的方式

void glPixelStoref(GLenum pname,GLint param);

以上两个了解即可,一般不需要做出改变。

3. 读取像素

将颜色缓存区的内容作为像素图直接读取

void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);

参数:
x : 从哪个位置开始读取,x坐标,一般选择矩形左下角的窗口坐标。

y : 从哪个位置开始读区,y坐标,一般选择矩形左下角的窗口坐标。

width : 读取的这张图片的宽是多少,矩形的宽,以像素为单位。

height : 读取的这张蹄片的高是多少,矩形的高,以像素为单位。

format : 读取图片要用的像素模式。详情见下图1.1。(用的一般都是RGBA)

type : 解释下一个参数pixels指向的数据,就是选择颜色缓存区中的哪种数据类型来存储颜色分量。也就是像素数据的数据类型,详见下图1.2。

*pixels : 指向图形数据的指针。就是你要把数据读取到哪里。

1.1.png 1.2.png

备注:
用的很少。
可以指定读取的缓存:glReadBuffer(mode);
可以指定写入的缓存:glWriteBuffer(mode);

4. 载入纹理

载入一维纹理(很少用):

void glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

载入二维纹理(常用):

void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)

载入三维纹理(很少用):

void glTexImage3D (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

载入二维纹理的参数:
target : 给定一个标记,确定要载入几维的纹理。GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D

level : 指定所加载的mip贴图层次。纹理是可以堆叠的,一般都一张不堆叠,所以一般都设置成0,但是可以设置纹理在第几层。

internalFormat: 每个纹理单元中存储多少颜色成分。

width: 加载纹理的宽度。老版OpenGL这个数值必须是2的整数次方,现在没这个规定了,但是大家还是按照老规矩来做了。

height: 加载纹理的高度。要求同上

border: 允许为纹理贴图添加一个边框,给定一个边界限度,一般没人用。

format: 载入纹理要用的像素模式。详见图1.1

type: 像素数据的数据类型。详见图1.2

*pixels: 指向纹理图像数据的指针。就是你要把数据载入到哪里。

5. 更新纹理

更新一维纹理(很少用):

void glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);

更新二维纹理(常用):

void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);

更新三维纹理(很少用):

void glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);

参数和载入纹理是一样的意思,唯独增加了xoffsetyoffset,这个很明显是偏移量。

6. 插入替换纹理

插入替换一维纹理(很少用):

void glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);

插入替换二维纹理(常用):

void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);

插入替换三维纹理(很少用):

void glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);

参数也是和载入纹理一样的意思,offset也是偏移量,而GLSizei数据类型的参数表示的是更新多大的纹理,更新的纹理的位置坐标。

7. 复制纹理

复制一维纹理:

void glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);

复制二维纹理:

void glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);

没有复制三维纹理,因为无法从2D颜色缓存区中读取到体积这种变量。
这里的x,y指的是在颜色缓存区中,开始读取纹理数据的位置。

8. 纹理对象

这几个函数是一定要写的,都是固定的,记下来就好了。

指定纹理对象的数量(n)和指针(*textures),指针指向的是无符号整型数组,由纹理对象标识符填充。

void glGenTextures (GLsizei n, GLuint *textures);

void glBindTexture (GLenum target, GLuint texture);

参数:

target: GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D

texture: 需要绑定的纹理对象。

纹理对象以及纹理对象指针,指针指向一个无符号纹理对象数组,由纹理对象标示符填充。

void glDeleteTextures (GLsizei n, const GLuint *textures);

判断依据就是上面指定的标识符,也就是如果texture是一个已经分配了空间的纹理对象,那么这个函数就会返回GL_TRUE,否则返回GL_FALSE

GLboolean glIsTexture (GLuint texture);

9. 设置纹理的相关参数

void glTexParameterf (GLenum target, GLenum pname, GLfloat param);
void glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
void glTexParameteri (GLenum target, GLenum pname, GLint param);
void glTexParameteriv (GLenum target, GLenum pname, const GLint *params);

参数:

target : 指定这些参数要使用在哪种纹理模式上。GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D

pname : 你想设置纹理的哪一个属性。指定要设置的纹理参数名。

param : 你想设置的纹理的那个属性要设置的值。指定纹理参数值。

10. 设置过滤方式

纹理有两种过滤方式,如下图所示的图1.3是邻近过滤(GL_NEAREST),如图1.4是线性过滤(GL_LINEAR)

1.3.png 1.4.png

邻近过滤取的是离该像素点最近的颜色的值,而线性过滤取的是该像素点周围颜色的综合值(混合),纹理坐标在哪里,哪个颜色的值占比就多一点。

一般情况下,当纹理缩小时,选择使用邻近过滤:

glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

当纹理放大的时候,选择使用线性过滤

glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_ LINEAR);

当然这个只是建议,可以随意设置。

11. 设置环绕方式

当纹理坐标超出了默认范围时,可以选择不同的环绕方式来填充。一共有四种环绕方式,如下图1.5所示:

1.5.png

举例一下:

void glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

参数:

target : 指定这些参数要使用在哪种纹理模式上。GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D

pname :这里用的是str坐标,设置对应轴上的环绕方式,s对应x,t对应y,r对应z,q对应w ,可以选择:GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T,GL_TEXTURE_WRAP_R

param : 如图1.5,自己选一个。

总结一下本节,一定要记住一套API:

  1. 读取文件
    2.载入纹理
    3.纹理对象

本节关于OpenGL的API的学习就到此结束。

上一篇下一篇

猜你喜欢

热点阅读