美文网首页
第十六节—纹理常用API

第十六节—纹理常用API

作者: L_Ares | 来源:发表于2020-09-01 23:25 被阅读0次

    本文为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的学习就到此结束。

    相关文章

      网友评论

          本文标题:第十六节—纹理常用API

          本文链接:https://www.haomeiwen.com/subject/plfbsktx.html