纹理映射基础

转载:http://www.360doc.com/content/14/1028/09/19175681_420504132.shtml

1.纹理映射基本概念
纹理映射使用一个图案或者纹理来确定渲染流水线中片元处理阶段片元的颜色。

简单来讲,纹理就是矩形的数据数组,例如颜色数据、亮度数据、颜色和alpha数据。纹理数组中的单个值常常称为纹理单元,也叫纹素(texel),这里让它区别于像素,主要是为了强调它的应用方式。

OpenGL支持1D、2D、3D以及立方体纹理,现在主要考虑2D纹理。

纹理映射就是要实现,如何把纹素映射到几何对象的每个点。一个2D的纹理有一个宽度和高度,通过宽度和高度相乘即可得到有多少个纹素。

那么如何来指定顶点的纹素呢?通过坐标来指定,但是这个坐标不应该是具体纹理的中坐标,而应该是抽象的纹理坐标空间中的坐标;否则通过指定具体纹理的坐标,当更换纹理,例如改变纹理的宽度和高度时,这些坐标值可能变得无意义,而不得不更新所有顶点的坐标值,因此需要使用抽象的纹理坐标空间的坐标。纹理坐标一般都规范化到[0,1]范围内。例如一个纹理宽度为320,高度为200,而纹理坐标(0.5,0.1)则表示纹素的位置在: (320*0.5,200*0.1)=(160,20)。通常使用UV坐标系来表示纹理坐标系:

这里写图片描述

这里注意,OpenGL中V轴从下往上是正方向,U轴从左往右是正方向。在具体使用时,这与应用中纹理Y方向有关。如果纹理从上到下,则需要将纹理的Y方向翻转来满足这个图形所示的纹理坐标。

与纹理映射有关的一个特性是,当模型进行变换时,纹理坐标仍然会跟着模型的顶点,他们并不进行变换(当然也有其他方法可以改变纹理坐标),就好像粘着顶点一样。例如下图所示的三角形,如果在其中应用一个小的纹理:
这里写图片描述

当对三角形进行变换时,纹理坐标保持不变,这样当模型进行旋转、拉伸和放缩时,纹理也会跟着变化,如下图所示:

这里写图片描述

与纹理有关的另一个特性是纹理采样。当把纹理坐标映射到纹素数组时,正好得到对应纹素的中心位置的情况很少出现。解决这一问题的一种方法是,从纹素数组中取这样一个纹素,该纹素的位置,最佳逼近通过光栅化模块计算输出的纹理坐标。这样一方法成为点采样(Point sampling),也叫做nearest filtering。例如坐标(152.34,745.14)的纹素,就使用(152,745)来代替。用点采样容易产生走样误差。

另外一种方法是线性滤波方法(linear filtering)。例如,如果计算出一个纹理坐标位于(152.34,745.14),那么这个值对应的最近的4个纹理坐标为: ( (152,745), (153,745), (152,744) , (153,744) )。那么我们可以利用这4个纹理坐标的对应的颜色值进行线性插值,例如计算这一组纹素的加权平均值,并把该值作为纹理坐标映射到纹素数组时的纹素值。这种方法计算量要比点菜用大,效果一般比点采样好。

OpenGL支持多种滤波类型,可以通过设置来进行选择。

在进行纹理映射时,还需要考虑纹素与屏幕像素之间的对应关系。单个的纹素通常并不与屏幕像素对应,当纹素比单个像素大时,屏幕上多个像素对应于单个像素,称之为放大(manification);当纹素比单个像素小,屏幕上单个像素对应多个纹素,则称之为缩小(minification)。关系如下图所示(来自[2]):

这里写图片描述

2.纹理映射OpenGL实现
OpenGL中纹理映射的步骤如下:

(1)创建纹理对象,并为他指定一个纹理
(2)确定纹理如何应用到每个像素上
(3)启用纹理贴图功能
(4)绘制场景,提供纹理坐标和几何图形坐标

这里参考的是红宝书的步骤,实际上采用着色器方式的话流程稍微有所不同,主要是纹理坐标和几何图形坐标,可能在绘制场景之前在着色器中已经提供了。

实现纹理映射主要关系到4个概念:纹理对象(the texture object), 纹理单元(the texture unit), 采样器对象(the sampler object )采样器变量(sampler uniform in the shader).他们的关系如下图所示:

这里写图片描述

纹理对象包含了纹理数据,它可以是1D、2D、3D的,底层数据可以是RGB、RGBA格式的。

纹理对象并不直接绑定到着色器,而是绑定到一个纹理单元,纹理单元的索引将会传递给着色器。要绑定到一个纹理单元,先要将其激活,可以使用glActiveTexture函数,例如glActiveTexture(GL_TEXTURE0)将激活单元0。可以使用多个纹理单元,每个纹理单元可以绑定到相同或者不同的纹理对象。有一点值得注意,只要纹理对象的类型不同,一个纹理单元可以绑定多个纹理对象。例如你可以分别将两个纹理对象绑定到同一个纹理单元的1D和 2D不同的目标上。

你可以通过采样器变量来使用多个纹理,这个uniform变量有’sampler1D’, ‘sampler2D’, ‘sampler3D’, ‘samplerCube’等不同形式。在片元着色器中,采样函数需要通过采样器变量来访问多个纹理单元。

采样器对象与纹理对象不相同。纹理对象中包含了纹理数据,以及配置采样操作的参数,这些参数是采样状态的一部分。然而,你也可以创建一个采样对象,用采样状态参数配置它,并把它绑定到纹理单元中。这样,采样器对象会覆盖纹理对象中定义的采样状态。目前我们并不使用这一对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值