美文网首页
OpenGL纹理API简介

OpenGL纹理API简介

作者: 瀚_ | 来源:发表于2019-06-15 15:45 被阅读0次

纹素和纹理坐标

纹理对象通常是通过纹理图片读取到的,这个数据保存到一个二维数组中,这个数组中的元素成为纹素(texel),纹素包含颜色值和alpha值。纹理对象的大小的宽度和高度应该为2的整数幂,例如16,32,64。要想获取纹理对象中的纹素,需要使用纹理坐标(texture coordinate)指定。

纹理坐标应该与纹理对象大小无关,这样指定的纹理坐标当纹理对象大小变更时,依然能够工作,比如从256x256大小的纹理,换到512x256时,纹理坐标依然能够工作。因此纹理坐标使用规范化的值,大小范围为[0,1],纹理坐标使用uv表示,如下图所示:


纹理坐标.png

通过指定纹理坐标,可以映射到纹素。例如一个256x256大小的二维纹理,坐标(0.5,1.0)对应的纹素即是(128,256)。

纹理映射时只需要为物体的顶点指定纹理坐标即可,其余部分由片元着色器插值完成,如下图所示:


纹理映射.png

纹素到像素转换问题

  • 一个纹素最终对应屏幕上的多个像素称为放大(magnification)

  • 一个纹素对应屏幕上的一个像素 这种情况不需要滤波方法

  • 一个纹素对应少于一个像素,或者说多个纹素对应屏幕上的一个像素称为缩小(minification)

    放大缩小示意图.png

Mipmaps

当物体在场景中离观察者很远,最终只用一个屏幕像素来显示时,这个像素该如何通过纹素确定呢?如果使用最近邻滤波来获取这个纹素,那么显示效果并不理想。需要使用纹素的均值来反映物体在场景中离我们很远这个效果,对于一个 256×256的纹理,计算平均值是一个耗时工作,不能实时计算,因此可以通过提前计算一组这样的纹理用来满足这种需求。这组提前计算的按比例缩小的纹理就是Mipmaps。Mipmaps纹理大小每级是前一等级的一半,按大小递减顺序排列为:

  • 原始纹理 256×256
  • Mip 1 = 128×128
  • Mip 2 = 64×64
  • Mip 3 = 32×32
  • Mip 4 = 16×16
  • Mip 5 = 8×8
  • Mip 6 = 4×4
  • Mip 7 = 2×2
  • Mip 8 = 1×1

OpenGL中通过函数glGenerateMipmap(GL_TEXTURE_2D);来生成Mipmap,前提是已经指定了原始纹理。
如果直接在不同等级的MipMap之间切换,会形成明显的边缘,因此对于Mipmap也可以同纹素一样使用滤波方法在不同等级的Mipmap之间滤波。要在不同等级的MipMap之间滤波,需要将之前设置的GL_TEXTURE_MIN_FILTER选项更改为以下选项之一:

  • GL_NEAREST_MIPMAP_NEAREST: 使用最接近像素大小的Mipmap,纹理内部使用最近邻滤波。
  • GL_LINEAR_MIPMAP_NEAREST: 使用最接近像素大小的Mipmap,纹理内部使用线性滤波。
  • GL_NEAREST_MIPMAP_LINEAR: 在两个最接近像素大小的Mipmap中做线性插值,纹理内部使用最近邻滤波。
  • GL_LINEAR_MIPMAP_LINEAR: 在两个最接近像素大小的Mipmap中做线性插值,纹理内部使用线性滤波。

使用使用glGenerateMipmap(GL_TEXTURE_2D)产生Mipmap的前提是你已经加载了原始的纹理对象。使用MipMap时设置GL_TEXTURE_MIN_FILTER选项才能起作用,设置GL_TEXTURE_MAG_FILTER的Mipmap选项将会导致无效操作,OpenGL错误码为GL_INVALID_ENUM。

片元着色器中使用纹理对象

在顶点着色器中我们传递了纹理坐标,有了纹理坐标,获取最终的纹素使用是在片元着色器中完成的。由于纹理对象通过使用uniform变量来向片元着色器传递,实际上这里传递的是对应纹理单元(texture unit)的索引号。纹理单元、纹理对象对应关系如下图所示:


纹理单元和纹理对象对应关系图.png

着色器通过纹理单元的索引号索引纹理单元,每个纹理单元可以绑定多个纹理到不同的目标(1D,2D)。OpenGL可以支持的纹理单元数目,一般至少有16个,依次为GL_TEXTURE0 到GL_TEXTURE15,纹理单元最大支持数目可以通过查询GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS常量获取。这些常量值是按照顺序定义的,因此可以采用 GL_TEXTURE0 + i 的形式书写常量,其中整数i在[0, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)范围内。

纹理对象不仅包含纹理数据,还包含采样参数,这些采样参数称之为采样状态(sampling state)。而采样对象(sampler object)就是只包含采样参数的对象,将它绑定到纹理单元时,它会覆盖纹理对象中的采样状态,从而重新配置采样方式。

要使用纹理必须在使用之前激活对应的纹理单元,默认状态下0号纹理单元是激活的,因此即使没有显式地激活也能工作。激活并使用纹理的代码如下:

        ```
        glActiveTexture(GL_TEXTURE0)
        ```

纹理API

  • 读取文件
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);

format: 像素格式
type: 解释参数pixels指向的数据,告诉OpenGL使用缓存区中的什么数据类型来存储颜色分量。像素数据的数据类型
pixels: 图形数据指针
像素格式.png 像素数据的数据格式.png
GLbyte *gltReadTGABits(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat);

szFileName: 纹理文件名
iWidth: 宽度地址
iHeight: 高度地址
iComponents: 组件地址
eFormat: 格式地址
  • 载入纹理
void glTextImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data)

target: `GLTETURE_1D`  `GL_TEXTURE_2D`  `GL_TEXTURE_3D`
level:  指定所加载的mip贴图层次,一般设置为0
internalformat: 每个纹理单元中存储多少颜色成分
format: 像素格式(如: GL_RGBA)
type: 像素数据的数据类型(GL_UNSIGNED_BYTE, 每个颜色分量都是一个8位无符号整数)
data: 指向纹理图像数据的指针
  • 纹理对象

    • 分配纹理对象

      glGenTextures(GLsizi n, GLuint *textures);
      
    • 绑定纹理状态

      glBindTexture(GLenum target, GLuint texture);
      
    • 删除绑定纹理

      void glDelteTextures(GLsizei n, GLuint *textures);
      
    • 测试纹理对象是否有效

      GLboolean glIsTexture(GLuint texture);
      
  • 设置纹理的相关参数

glTexParameteri(GLenum target, GLenum pname, GLint param);
  • 过滤方式

    • 邻近过滤(GL_NEAREST)

       // 纹理缩小时,使用邻近过滤
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      
    • 线性过滤(GL_LINEAR)

       // 纹理放大时,使用线性过滤
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      
  • 环绕方式

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
  • 纹理隧道Demo

参考:
https://blog.csdn.net/wangdingqiaoit/article/details/51457675

相关文章

  • OpenGL纹理API简介

    纹素和纹理坐标 纹理对象通常是通过纹理图片读取到的,这个数据保存到一个二维数组中,这个数组中的元素成为纹素(tex...

  • OpenGL纹理API简介

    以下为经常使用的纹理API笔记, 仅做记录学习 1. 读取文件 2. 载入纹理 至于glTexImage1D,gl...

  • OpenGL纹理 - 常用API简介

    原始图像数据与内存包装 图像的存储空间= 图像的宽度 * 图像的高度 * 每个像素的字节数(系统决定) 内存对齐:...

  • OpenGL纹理API

    一、认识纹理 现在我们能够通过计算颜色值对它们的表面进行着色,以及在它们之间进行插值操作来模拟光照效果。但是为了达...

  • OpenGL纹理API

      在了解纹理相关的API之前,我们需要了解到,png和jpg的图片,在计算机内部,要先将图片解码成位图,然后才能...

  • OpenGL纹理API

    首先我们需要知道无论是OpenGL中的纹理文件(tga格式),还是日常开发所使用的的图片(png等常见图片格式),...

  • OpenGL 纹理API

    1.纹理 在OpenGL中,我们读取的png,jpeg等一些格式的图片,在GPU中最终会被压缩成纹理(位图)。假设...

  • OpenGL纹理简介

    1、了解纹理 图像的存储空间 = 图片width * 图片height * 每个像素的字节数 OpenGL纹理文件...

  • OpenGL学习(第1节) Api基本简介和专业名词

    1、OpenGL / OpenGL ES图形API基本简介 OpenGL(Open Graphics Librar...

  • OpenGL 纹理相关API

    图片在屏幕上的显示,最终都是解码成位图,然后进行显示的。一个图形在帧缓存区中的存储空间,可以根据如下公式计算,图像...

网友评论

      本文标题:OpenGL纹理API简介

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