OpenGL蓝宝书源码学习(十)第五章——纹理的应用、Mip贴图、各项异性过滤和纹理压缩基础

一、纹理应用

1、纹理坐标

我们是通过为每个顶点指定一个纹理坐标而直接在几何图形上进行纹理贴图的。纹理坐标要么是指定为着色器的一个属性,要么通过算法计算出来。纹理贴图中的纹理单元是作为一个更加抽象的纹理坐标,而不是作为内存位置进行寻址的。典型情况下,纹理坐标作为0.0到1.0范围内的浮点值指定的。纹理坐标命名为s、t、r和q,支持从一维到三维的纹理坐标,并且可以选择一种对坐标进行缩放的方法。q是一个缩放因子,作用于其他纹理坐标。一个纹理坐标会在每个顶点上应用一个纹理。然后,OpenGL根据需要对纹理进行放大或缩小,将纹理贴图到几何图形上。通过下图理解:


纹理的角对应于几何图形的角。

2、纹理参数

通过glTexParameter函数和其中的参数变量来设置纹理参数,来影响渲染的规则和纹理贴图的行为。


target指定这些参数将要应用在哪个纹理模式上,它可以是GL_TEXTIRE1D、GL_TEXTIRE2D、GL_TEXTIRE3D。

pname指定需要设置哪个纹理参数。

param或params用于设置特定的纹理参数的值。

1)基本过滤

纹理图像中的纹理单元和屏幕上的像素几乎从来不会形成一对一的关系。但是,也确实可以实现这个效果,需要在对几何图形进行纹理贴图时进行精心的计划,使出现在屏幕上的纹理单元和像素能够对齐。因此,当纹理应用于与几何图形的表面时,纹理图像不是不是被拉伸就是被收缩。根据一个拉伸或收缩的纹理贴图计算颜色片段的过程称为纹理过滤。

放大过滤参数:GL_TEXTURE_MAG_FILTER

缩小过滤参数:GL_TEXTURE_MIN_FILTER

最邻近过滤器:GL_NEAREST

线性过滤器:GL_LINEAR。

确保总是为GL_TEXTURE_MIN_FILTER选择这两种过滤器中的一种,因为默认的过滤器不适用于Mip贴图

纹理坐标总是根据纹理图像的纹理单元进行求值和绘图的。不管纹理坐标位于哪个纹理单元,这个纹理单元的颜色就作为这个片段的纹理颜色。

例如,使用glTexParameter函数,为放大和缩小过滤器设置纹理过滤器


线性过滤器并不是把最邻近的纹理单元应用到纹理坐标中,而是把这个纹理坐标周围的纹理单元的加权平均值应用到这个纹理坐标上(线性插值)。为了让这个插值的片段与纹理单元的颜色准确匹配,纹理坐标需要准确地落在纹理单元的中心。


2)纹理环绕

正常情况下,在0.0到1.0的范围之内指定纹理坐标,使他与纹理贴图的纹理单元形成映射关系。如果纹理坐标落在这个范围之外,OpenGL则根据当前纹理环绕模式处理这个问题。可以调用glTexParameteri函数,并分别使用GL_TEXTURE_WARP_S、GL_TEXTURE_WARP_T或GL_TEXTURE_WARP_R作为参数,为每个坐标分别设置环绕模式。环绕模式设置如下:

GL_REPEAT:重复模式。在纹理坐标值超过1.0的方向上对纹理进行重复。在重复模式中,相当于环绕到纹理的另一边。对于沿物体环绕并与另一边吻合的纹理(例如球体),这种模式是相当完美的。

GL_CLAMP:截取模式。典型的应用就是在必须对一块大型区域进行纹理处理时。

二、Mip贴图

Mip贴图时一种功能强大的纹理技巧,他不仅可以提高渲染性能,而且可以改善场景的显示质量。它使用标准纹理贴图处理两个常见的问题,从而实现上述目标。

问题1,闪烁:当屏幕上被渲染的物体的表面与它所应用的纹理图像相比显得非常小时,就会出现这种效果。闪烁可以看成是某种类型的闪光,当纹理图像的采样区域的移动幅度与它在屏幕上的大小相比显得不成比例时,就会发生这种现象。当照相机或物体处于运动状态时,很容易看到闪烁的负面效果。

问题2,和性能有关,原因和闪烁相同。即问题的根源在于它必须加载大量的纹理内存并对他们进行过滤处理,但屏幕上实际显示的只是很少的一部分片段。

从本质上说,不是把单个图像加载到纹理状态中,而是把一系列从最大到最小的图像加载到单个“Mip贴图”纹理状态。Mip贴图纹理由一系列纹理图像组成,每个图像大小在每个轴的方向上都缩小一半,或者说是原来图像像素总数的四分之一。

Mip贴图层是通过glTexImage函数加载的。level参数可以发挥它的作用了,它指定了图像数据用与哪个Mip层。第一层是0,接着是1、2,以此类推。如果Mip贴图未被使用,那么他就只有第0层被加载。默认情况下,为了使用Mip贴图,所有的Mip层都必须被加载。但是,可以使用GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL纹理参数特别设置需要使用的基层和最大层。

例如,如果想指定只加载第0层到第4层,可以像下面一样调用glTexParameter函数两次:


但是,也可以使用GL_TEXTURE_MIN_LOD和GL_TEXTURE_MAX_LOD参数限制已加载的Mip层的使用范围。

1、Mip贴图过滤

Mip贴图在两个基本的纹理过滤模式GL_NEARSET和GLLINER上添加了一个新的变化,这是通过向Mip贴图过滤模式提供4中不同变化实现的。下面列出:


我们必须指定下面4个的其中一个Mip贴图过滤器,这样才能使用所有已加载的Mip层。上面两个只能使用纹理贴图的基层。

2、生成Mip层

对纹理的Mip层进行预先计算会得到最好的结果,同时让为我们生成纹理是非常方便的,也是比较普遍的方式。一旦通过glGenerateMipmap函数加载了第0层,就可以为纹理生成所有的Mip层了。

void glGenerateMipmap(GLenum target);

目标参数可以是GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D、GL_TEXTURE_CUBE_MAP、GL_TEXTURE_1D_ARRAY或GL_TEXTURE_2D_ARRAY。

在运行过程中生成Mip贴图通常比预加载创建的Mip贴图要慢,所以要加载自己预先生成的Mip贴图。

三、各向异性过滤


应用各向异性过滤需要3个步骤:

1、必须确认这种扩展是得到支持的。可以使用glTools函数gltExtensionSupported完成这个任务。

if(gltIsExtSupported("GL_EXT_texture_filter_anisotropic"))

2、在确认扩展得到支持只后,就可以查询得到支持的各向异性过滤的最大数量。

GLfloat fLargest;

glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&fLargest);

各向异性过滤所应用的数量越大,沿最大变化方向(沿最强的观察点)所采样的纹理单元就越多。

3、设置想要应用的各向异性过滤的数量

glTexParameter(GL_TEXTURE_2D,GLTEXTURE_MAX_ANISOTROPY_EXT,fLargest)

各向异性过滤是以每个纹理对象为基础进行应用的,就像标准过滤参数一样。在Anisotropic.cpp的源码示例中在仔细地学习一下。

四、纹理压缩

纹理贴图可以在3D渲染场景中增加令人难以置信的逼真性,但是它们需要大量的内存来存储和处理纹理。所以OpenGL添加了对纹理压缩的本地支持。可以使用GL_ARB_texture_commpression字符串来测试这个扩展是否得到支持。

1、压缩纹理

为了利用OpenGL对压缩纹理的支持,纹理数据一开始并不需要进行压缩。可以在加载一幅纹理图像时请求OpenGL对他进行压缩,这是通过在glTexImage函数中把internalFormat参数设置为下边的任意一个值:


可以使用glGetTexLevelParameteriv函数(以GL_TEXTURE_COMPRESSED为参数)来判断这个纹理是否被成功压缩。

GLint compFlag;

glGetTexLevelParameteriv(GL_TEXTURE2D,0,GL_TEXTURE_COMPRESSED,&compFlag);

它接受下表的参数:


2、加载压缩纹理

用glGetCompressedTexImage函数提取经过压缩的数据并把它保存到磁盘中。在后续的纹理加载中,可以使用原始压缩数据,从而极大地提高纹理的加载速度。

为了加载预先经压缩的纹理数据,可以使用下列函数之一。


这些函数实际上与前一章的glTexImage函数等同,仅有的区别是这些函数的internalFormat参数必须指定一种受到支持的压缩纹理图像格式。

另外还有一组对应的glCompressedTexSubImage函数,用于更新已经加载的纹理,它们与glTexSubImage的功能相当。

注意:纹理压缩方法的选择(或选择不使用纹理压缩)可能极大地依赖于底层图像的本质。

五、小结

至此,第五章大概的知识点和概念的介绍就到此为止,后面还是进行第五章源码示例的解析学习,当然在源码的学习过程中,还要反复地查看纹理的基础知识以加深对纹理在3D渲染的应用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值