设为首页 加入收藏

TOP

OpenGL超级宝典学习笔记——纹理高级(一)(一)
2015-02-25 22:43:04 来源: 作者: 【 】 浏览:66
Tags:OpenGL 超级 宝典 学习 笔记 纹理 高级

辅助颜色


一般情况下,我们设置纹理的环境为GL_MODULATE模式,在这种情况下,受到光照的几何图形会和纹理的颜色进行结合。正常情况下,OpenGL进行光照计算,并根据标准的光照模型进行单个片段的颜色计算。然后,再把片段的颜色乘以纹理的颜色,等到结合后的颜色。但是这样的话会削弱图形的光照效果。因为经过光照计算过后的片段的颜色值最大值是1.0(即最亮的颜色),任何值乘以小于1.0的值,必定小于其本身(即不可能比原来更亮)。(if y <= 1.0 then x * y <= x. x y是正数)。


没有应用纹理之前:


image


应用纹理之后光照效果被削弱了:


image


要解决这个问题,我们可以在纹理映射之后再应用镜面光高亮的效果(通过加而不是乘的方式)。这个技巧成为辅助镜面光颜色。通过设置光照的模型来达到此目的,函数调用如下:


glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);


加了这一行之后的效果如下:


image


要切回正常状态,指定光照模型为GL_SINGLE_COLOR即可,函数调用如下:


glLightModeli(GL_LIGHT_COLOR_CONTROL, GL_COLOR_SINGLE);


使用没有开启光照,我们可以手动来设置辅助颜色,通过glSecondarycolor函数调用设置辅助颜色和通过glEnable(GL_COLOR_SUM);来开启。手动设置的辅助颜色只有在没有开启光照的情况下有作用。


?


各向异性过滤并非OpenGL核心API的一部分,但其作为扩展被广泛用于提升纹理过滤操作的质量。在先前学习的两个基本的过滤器最邻近过滤(GL_NEAREST)和线性过滤(GL_LINEAR)。OpenGL使用纹理坐标计算得到纹理将映射到几何图形的哪一个片段上。然后通过对该位置周围的纹理元素以GL_NEAREST过滤或GL_LINEAR过滤方式进行采样。


当我们的视角是垂直于该几何图形的时候,这样的方式没有问题。然而当我们的视角与几何图形形成一个斜角的时候,以常规的方式对周边纹理进行采样会丢失一些纹理的信息,它看起来变模糊了。更真实和精确的采样是,沿着平面倾斜的方向,拉长纹理的采样。如下的第二个图:


image


我们可以把各向异性过滤应用去基本的和mipmap方式的纹理过滤模式上。在使用之前我们需要检查各向异性过滤扩展是否被支持,使用glTools函数里的函数:


if(gltIsExtSupported(“GL_EXT_texture_filter_anisotropic”))


如果扩展是被支持的,我们可以查到支持各向异性过滤的最大值。通过调用glGetFloatv参数为GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT。


GLfloat fLargest;


glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);


值越大各向异性过滤的粒度越大,如果值为1.0就代表普通的纹理过滤。各向异性过滤会带来一定的开销。现代的显卡都已经支持各向异性过滤,而且做了优化。最后我们通过glTexParameterf函数来设置各向异性过滤的最大值,如下:


glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);


非开启各向异性过滤的通道效果图,可以看到远处的砖块较模糊:


image


开启各向异性过滤之后的效果图:


image


?


使用纹理的缺陷是纹理需要大量的内存来存储和处理。在早期我们会把纹理压缩成JPG的格式,然后在加载之前(调用glTexImage之前)对其进行解压。这样仅仅是节省了磁盘的空间以及加快了在网络上传输纹理的速度,但并没有减少对显存(加载到显存中还是原格式那么大)。


在OpenGL1.3后,OpenGL原生支持了纹理压缩的特性。在更低的版本中,通过扩展来支持,你可以通过GL_ARB_texture_compression来检查是否支持这个扩展。OpenGL对纹理的压缩不仅仅是加载压缩的纹理,而且在显卡内存中也是保存着压缩的纹理。这可以减少加载纹理时使用的内存以及提升处理纹理的性能(减少了移动纹理和切换纹理的时间,因为要操作的内存空间变小了)。


你可以通过下表的一个常量作为glTexImage函数中internalFormat参数的值,来达到压缩纹理的目的。当纹理无法被压缩时,将使用对应的基本内部格式。


在这种方式下,加载压缩的图像会多耗一点时间,但却提升了处理纹理内存的速度。但你使用这种方式压缩了纹理之后,你可以通过glGetTexLevelParameteriv参数为GL_TEXTURE_COMPRESSED来检查纹理是否压缩成功。


GLint compFlag;


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


此函数接受的参数如下表:


我们还可以通过glHint函数来告诉OpenGL我们要用的是最快的压缩算法还是最高质量的压缩算法。通过使用GL_NUM_COMPRESSED_TEXTURE_FORMATS和GL_COMPRESSED_TEXTURE_FORMATS来获得被支持的压缩格式的列表。几乎所有的OpenGl实现都支持GL_EXT_texture_compression_s3tc纹理压缩格式,如果这个扩展被支持那下面表格的所有格式都是支持的(仅适用于2维纹理)


?


在前面我们已经介绍了,如何压缩纹理数据。然后我们可以通过glGetCompressedTexImage(与glGetTexImage获取未压缩数据一样)来获取被压缩的数据,并把它存到硬盘上。在随后的加载中,直接加载已经压缩过的纹理数据会更快。此技术完全依赖于硬件的实现。


加载已经预先压缩过的纹理数据,可以调用下面的函数:


void glCompressedTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, void *data);


void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, void *data);


void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLint width, GLint height, GLint depth, GLint border, GLint imageSize, void *data);


这个方法与glTexImage几乎是一样的,不一样的是其internalFormat必须是压缩的格式。如果实现支持GL_EXT_texture_compression_s3tc扩展,那么其参数值就可以是上面的表格列出的值。当然也有glCompressedTexSubImage函数来更新部分已加载的压缩过的纹理数据,就像glTexSubImage

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenGL超级宝典学习笔记——纹理.. 下一篇OpenGL超级宝典学习笔记——纹理..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: