OpenGL中的纹理

作者: 黑眼豆豆_ | 来源:发表于2020-07-22 15:28 被阅读0次

什么是纹理

纹理(texture),通常来说,纹理就是一张二维的图片。给一个模型贴一个纹理,就像在iOS代码中添加UIImage一样。

  • 像素包装

图像存储空间 = 图像的宽度 * 图像的长度 * 每个像素的字节数

  • tga文件
    在OpenGL中,我们使用.tga文件作为纹理的素材,该格式支持压缩,使用不失真的压缩算法,可以带通道图,另外还支持行程编码压缩。
    但是在OpenGL ES里面,我们就可以使用正常的图片了,例如.png,.jpg等等了。

其实任何图片在绘制的时候都会被解压成位图,最终以位图的形式“贴在”模型上。

常用纹理函数

  • 从颜色缓冲区读取像素
    该方法就是把图片从帧缓冲区中读取出来并进行写入
//参数1:x,矩形左下⻆的窗⼝坐标
//参数2:y,矩形左下⻆的窗⼝坐标
//参数3:width,矩形的宽,以像素为单位
//参数4:height,矩形的⾼,以像素为单位
//参数5:format,OpenGL 的像素格式,参考图一
//参数6:type,解释参数pixels指向的数据,告诉OpenGL 使⽤缓存区中的什么数据类型来存储颜⾊分量,像素数据的数据类型,参考 图二
//参数7:pixels,指向图形数据的指针
void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei height, GLenum format, GLenum type,const void * pixels);

glReadBuffer(mode);—> 指定读取的缓存
glWriteBuffer(mode);—> 指定写⼊的缓存

  • 载入纹理
    载入纹理有以下3个方法
//纹理为1D格式
void glTexImage1D(GLenum target,GLint level,GLint 
internalformat,GLsizei width,GLint border,GLenum 
format,GLenum type,void *data);
//纹理为2D格式
void glTexImage2D(GLenum target,GLint level,GLint 
internalformat,GLsizei width,GLsizei height,GLint 
border,GLenum format,GLenum type,void * data);
//纹理为3D格式
void glTexImage3D(GLenum target,GLint level,GLint 
internalformat,GLSizei width,GLsizei height,GLsizei 
depth,GLint border,GLenum format,GLenum type,void *data);

这3个方法很类似,从方法名我们可以得知,3个方法的区别在于载入纹理的格式,究竟是1D,2D还是3D。函数每个参数的意义如下:

  • target为别对应GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
  • Level指定所加载的mip贴图层次。⼀般我们都把这个参数设置为0。
  • width、height、depth参数:指加载纹理的宽度、⾼度、深度。==注意!==这些值必须是2的整数次⽅。(这是因为OpenGL 旧版本上的遗留下的⼀个要求。当然现在已经可以⽀持不是2的整数次⽅。但是开发者们还是习惯使⽤以2的整数次⽅去设置这些参数。)
  • border允许为纹理贴图指定⼀个边界宽度。
  • format、type、data参数:与我们在讲glDrawPixels 函数对于的参数相同。

由于,图片通常为2D的,即有宽度和高度,所以我们通常使用** glTexImage2D**这个方法

  • 分配纹理对象
//参数1:使用了几个纹理,n就填几
//参数2:纹理对象指针,表示申请了一个纹理对象
void glGenTextures(GLsizei n,GLuint * textTures);
  • 绑定纹理
//参数1有以下几个类型GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D,需要结合我们的纹理使用,一般使用GL_TEXTURE_2D。
//参数2表示需要绑定的纹理对象
void GLAPIENTRY glBindTexture (GLenum target, GLuint texture)
  • 删除纹理
//参数1表示需要删除的纹理的个数。
//参数2表示需要删除的纹理对象,这是一个数组,表示可以删除多个纹理。
void glDeleteTextures (GLsizei n, const GLuint *textures);

设置纹理参数

设置纹理参数有以下几个方法:

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

上面的方法很类似,参数分别代表

  • target有以下几个类型GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D,需要结合我们的纹理使用,一般使用GL_TEXTURE_2D。
  • pname指定需要设置哪个纹理参数
  • params表示具体的参数的值

设置过滤方式

在OpenGL中过滤方式有2各种,一种叫做临近过滤(GL_NEAREST),一种叫做线性过滤(GL_LINEAR)

  • 临近过滤(GL_NEAREST)表示某个像素点会取当前位置上的颜色。
  • 线性过滤(GL_NEAREST)表情会取附近的颜色综合值,做混合后展示在屏幕上。
    临近过滤.png
    线性过滤.png
    用上图可以看出,图1就是选取的它所在位置的颜色,图2就是对它周围取了一个综合值,计算后得出一个最接近的值。
    接下来,我们可以看一个实际的图片:
临近过滤和线性过滤

我们可以看到,临近过去看起来会更加清晰,但是有锯齿状;而线性过滤则有点模糊的感觉,但是会平滑许多。
所以究竟选临近过滤还是线性过滤,其实需要根据当前的实际情况来判断。而且,在真实的案例中,2者并不会有太大差别。

  • 用法
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  • GL_TEXTURE_MAG_FILTER指当纹理图象被使用到一个大于它的形状上时的状态。
  • GL_TEXTURE_MIN_FILTER 指当纹理图象被使用到一个小于或等于它的形状上时的状态。

设置环绕方式,

当一个纹理坐标超出默认范围时,我们需要设置环绕方式,举个例子,假如我们的纹理为(44)的大小,但是我们的模型是(88),那么图片肯定不能铺满,那么就需要进行设置。

环绕方式.png
我们来看下具体效果:
  • GL_REPEAT
    GL_REPEAT.png
    此时,图片会进行复制,然后铺满屏幕。
  • GL_MIRRORED_REPEAT
    GL_MIRRORED_REPEAT.png
    此时,图片会进行复制,然后进行翻转,就像照镜子一样,然后铺满屏幕。
  • GL_CLAMP_TO_EDGE
    GL_CLAMP_TO_EDGE.png

此时,固定图片中心的位置,边缘部分会被拉伸。

  • GL_CLAMP_TO_BORDER
    GL_CLAMP_TO_BORDER.png

此时,固定图片中心的位置,超出部分用用户指定的颜色进行填充。

  • 用法
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  • GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_RGL_TEXTURE_WRAP_T分别代表s,t,r坐标。而这里的s,t,r坐标分别对应x,y,z坐标
  • 如果不设置,OpenGL默认使用** GL_REPEAT**。

纹理坐标系

对于一纹理来说,默认左下角为(0,0),右上角为(1,1)。


坐标系

如图所示,整个图片在[0,1]的区间中。

但是,我们也可以对图片进行翻转


翻转.png

如图,我们把图片翻转了180度之后仍然可以使用。

Mip贴图

Mip贴图这项材质贴图的技术,是依据不同精度的要求,而使用不同版本的材质图样进行贴图,可以提高渲染性能和显示质量。
例如:当物体移近使用者时,程序会在物体表面贴上较精细、清晰度较高的材质图案,于是让物体呈现出更高层、更加真实的效果;而当物体远离使用者时,程序就会贴上较单纯、清晰度较低的材质图样,进而提升图形处理的整体效率。

  • 用法
// 设置mip贴图基层
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
//设置mip贴图最⼤层 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
  • Mip贴图的纹理过滤方式
    Mip贴图的纹理过滤.png

下图为OpenGL的像素格式,我们常用GL_RGBGL_RGBA这两种格式。

图1.png

下图为OpenGL的像素数据的数据类型。我们常用GL_UNSIGNED_BYTE

图2.png

相关文章

  • OpenGL纹理内容

    纹理可以理解为一张图片,OpenGL渲染图片会将图片的像素保存在纹理缓存中。 OpenGL常用纹理函数 载入纹理 ...

  • OpenGL纹理

    纹理可以理解为一张图片,OpenGL渲染图片会将图片的像素保存在纹理缓存中。OpenGL常用纹理函数 载入纹理 纹...

  • OpenGL中的纹理

    OpenGL中的纹理可以用来表示图像、照片、视频画面等数据,在视频渲染中,只需要处理二维的纹理,每个二维纹理都由许...

  • OpenGL中的纹理

    什么是纹理 纹理(texture),通常来说,纹理就是一张二维的图片。给一个模型贴一个纹理,就像在iOS代码中添加...

  • GLKit常用API解析

    GLKTextureInfo 创建OpenGL纹理信息 name: OpenGL上下文中纹理名称 target: ...

  • OpenGL ES GLKit 􏰼􏰜常用API解析

    GLKTextureInfo创建OpenGL纹理信息 name : OpenGL上下文中纹理名称 target :...

  • OpenGL ES渲染视频之数据流

    相关概念 纹理纹理(Texture)纹理是一种图形数据,在OpenGL中可以简单理解成是一张图片纹理单元纹理的操作...

  • OPenGL ES纹理翻转解决方案

    纹理翻转 在使用OpenGL函数加载纹理到图形时,经常遇到纹理上下颠倒的问题。原因是因为OpenGL要求纹理坐标原...

  • 从0开始的OpenGL学习(五)-纹理

    本文主要解决一个问题: 在OpenGL中如何使用纹理? 一、什么是纹理? 纹理,英文是texture,中文可以翻译...

  • OpenGL之纹理及应用案例

    纹理介绍 OpenGL使用的图片数据(纹理)都是tga格式的,而iOS/OpenGL ES使用PNG/JPEG格式...

网友评论

    本文标题:OpenGL中的纹理

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