OpenGL蓝宝书源码学习(九)第五章——纹理基础篇

前言:

在学习超级宝典的源码之前,很有必要先把整个章节通读一遍,梳理一下知识点,理解一些概念的介绍和函数的用法,这样在后面源码学习的示例中才会得心应手。当然在学习第五章的每一个源码示例还要与基础知识串联起来,巩固学习,加强理解

一、原始图像数据

前四章的学习,已经对点、线和三角形组合的图形进行了渲染,也了解了如何能够通过计算颜色值对它们的表面进行着色,以及在它们之间进行插值来模拟光照效果。但是为了达到更加显示的效果,还有一种非常棒的捷径,就是纹理贴图。纹理只是一种能够应用到场景中的三角形的图像数据,它通过经过过滤的纹理单元填充到实心区域。当然,纹理远远不止是图像数据那么简单,它是大多数现代3D渲染算法的一个关键因素。

1、像素包装

一幅图像的每一行都应该从一种特定的字节对齐地址开始。OpenGL采用4个字节的对齐方式,这种方式适合于很多目前正在使用的系统。内存分配意图对OpenGL来说非常重要,因为在想OpenGL提交图像数据或从OpenGL获取图像数据时,OpenGL需要知道我们想要在内存中对数据进行进行怎样的包装或解包装。

使用下列函数改变或者恢复像素的存储方式。

void glPixelStorei(GLenum pname,GLint param);

void glPixelStoref(GLenum pname,GLint param);

2、像素图

在OpenGL核心版本中,我们无法直接讲一个像素图绘制到颜色缓冲区,但是可以使用下面的函数将颜色缓冲区的内容作为像素图直接读取。

void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei height,GLenum format,GLenum type,const void *pixels)

x和y值指定为矩形左下角的窗口坐标,然后再指定矩形的width和height值(像素值)

format指定pixel指向的数据元素的颜色布局,如下表5-2格式:


type解释参数*pixels指向的数据,他告诉OpenGL使用缓冲区中的什么数据类型来存储颜色分量,如下表5-3类型格式



*pixels是指向图像数据的指针,它必须是合法的,并且必须包含足够的存储空间来存储转换后的图像数据,否则会遇到严重的内存运行时异常。

3、包装的像素格式

包装的像素格式将颜色数据压缩到了尽可能少的存储位中,每个颜色通道的位置显示在常数中。例如,格式为第一个分量提供3位存储空间,为第二个分量也提供3位存储空间,而为第三个分量则提供了两位存储空间。请记住,指定的分量(红、绿、蓝和Alpha)的排列顺序仍然是根据format参数确定的。这些分量从高位到低位进行排列。

带有REV标志的类型的是按照相反的排序方式。

对于glReadPixel函数来说,读取操作在双缓冲区渲染环境下将在后台缓冲区进行,而在单缓冲区渲染环境在前台缓冲区进行,可以使用下面的函数改变这些像素操作的源:

void glReadBuffer(GLenum mode);

模式参数可以取GL_FRONT,GL_BACK,GL_LEFT,GL_FRONT_LEFT,GL_FRONT_RIGHT,GL_BACK_LEFT,GL_BACK_RIGHT或是GL_NONE中的任意一个。

4、保存像素

GLTools库中的gltWriteTGA函数从前台颜色缓冲区中读取颜色数据,并将这些数据存储到一个Targa文件格式的图像文件

5、读取像素

GLbyte *gltReadTGABits(const char *szFileName,GLint *Width,GLint *iHeight,GLint *iComponents,GLenum *eFormat)

第一个参数是将要载入的Targa文件的文件名。Targa图像格式是得到广泛支持的通用图像文件格式,与JPEG文件不同,JPEG文件(通常)以未经压缩的格式存储图像。

此函数用来打开文件,然后读入文件头并进行语法分析,以确定文件的宽度、高度和数据格式。分量的数量可以是1个、3个或4个,分别为亮度、RGB、或RGBA图像。最后的参数是一个指向GLenum的指针,它接受图像相应的GLenum图像格式。如果函数条用成功,它会返回一个新定位到直接从文件中读取的图像数据的指针。如果没找到文件,或者出现他去错误,函数则会返回NULL。

6、载入纹理

二、载入纹理

在几何图形中应用纹理贴图时,第一个必要步骤就是将纹理载入内存。一旦被载入,这些纹理就会成为当前纹理状态。有三个OpenGL函数最经常用来从存储器缓冲区中载入(比如说,从一个磁盘文件中读取)纹理数据。

这些函数实际上有同一个函数glTextImage派生出来的,支持一维、二维和三维。

注意:OpenGL会在调用这些函数中的一个时从data中复制纹理信息。这种数据复制会有很大的开销,后面学习如何减轻。

target变量分别为GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D。也可以使用代理纹理,方法是指定GL_PROXY_TEXTURE_1D、GL_PROXY_TEXTURE_2D、GL__PROXY_TEXTURE_3D,并使用glTexParameter函数提取代理查询的结果。后面学习。

level参数指定了这些函数所加载的mip贴图层次。后面学习。对于非mip贴图的纹理,总是把这个参数设置为0。

internalformat参数告诉OpenGL在每个纹理单元中存储多少颜色成分,并在可能的情况下说明这些成分的存储大小,以及是否希望对纹理进行压缩。

常用的纹理内部格式

width、height、depth参数指定了被加载纹理的宽度、高度和深度。注意,这些值必须是2的整数次方,这一点非常重要。

border参数允许为纹理贴图指定一个边界宽度。纹理边界允许对边界处的纹理单元进行额外的设置,来对它的宽度、高度和深度进行扩展。

最后三个参数format、type和data和用于把图像数据放入颜色缓冲区的glDrawPixels函数的对应参数相同。format和type与上面表5-2和表5-3对应。

1、使用颜色缓冲区

一维和二维纹理也可以从颜色缓冲区加载数据。可以从颜色缓冲区读取一幅图像,并通过下面的这两个函数将它作为一个新的纹理使用。



这两个函数的操作类似于glTextImage,但在这里x和y在颜色缓冲区中指定了开始读取纹理数据的位置。源缓冲区时通过glReadBuffer函数设置的。请注意,并不存在glCopyTexImage3D,因为我们无法从2D颜色缓冲区获取体积数据。颜色缓冲区是2D的,不存在一种对应方法将一幅2D彩色图像作为一个3D纹理的来源。

2、更新纹理

重新加载新纹理可能会成为性能瓶颈,替换一个纹理图像常常要比直接使用glTexImage重新加载一个新纹理快得多,函数glTexSubImage用于替换


绝大部分参数斗鱼glTexImage函数所使用的参数准确对应。xOffset、yOffset个zOffset参数指定了在原来的纹理贴图中开始替换纹理数据的偏移量。width、height和depth参数指定了“插入”到原来那个纹理中的新纹理的宽度、高度和深度。

最后一组函数允许从颜色缓冲区读取纹理,并插入或替换原来纹理的一部分。下面的函数是glCopyTexSubImage函数的变型:



这里,我们可以使用glCopyTexSubImage3D函数,在一个三维纹理中使用颜色缓冲区的数据来设置它的一个纹理单元平面。

3、纹理对象

纹理图像本身就是所谓的纹理状态的一部分。纹理状态包含了纹理图像本身和一组纹理参数,这些参数控制过滤和纹理坐标的行为。像glTexImage和glTexSubImage这样的函数调用所耗费的内存特别多。在纹理之间进行切换或者重新加载不同的纹理图像可能会是开销很大的操作。纹理对象允许我们一次加载一个以上的纹理状态(包括纹理图像),以及在他们之间进行快速切换。纹理状态是由当前绑定的纹理对象维护的,而纹理对象是由一个无符号整数标识的。

1)分配纹理

void glGenTextures(GLSizei n,GLuint *textures);

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

2)绑定纹理

void glBindTextures(GLenum target,GLuint texture);

target必须是GL_TEXTURE_1D、GL_TEXTURE_2D或GL_TEXTURE_3D,texture参数则是需要绑定的特定纹理对象。此后,所有的纹理加载和纹理参数设置只是影响当前绑定的纹理对象。

3)删除纹理对象

void glDeleteTextures(GLSizei n ,GLuint *textures);

参数和glGenTextures函数的参数具有相同的意义。多次调用glDeleteTexture可能会造成一些延迟。

4)纹理对象测试

GLboolean glIsTexture(GLuint texture);

如果texture参数是一个以前已经分配的纹理对象名,那么这个函数会返回GLTRUE,否则它就返回GL_FALSE。

三、小结

加载纹理只是在几何图形上应用纹理的第一步。最低限度我们必须同时提供纹理坐标,并设置纹理坐标环绕模式和纹理过滤。最后,可以选择对纹理进行Mip贴图,以提高纹理贴图性能和视觉质量。在后面的学习中,通过源码的学习来掌握纹理的应用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值