1.37k likes | 1.71k Views
Chapter 5. Texturing 纹理贴图. 金小刚 Email: jin@cad.zju.edu.cn http://www.cad.zju.edu.cn/home/jin 浙江大学 CAD&CG 国家重点实验室. “All it takes is for the rendered image to look right” —— Jim Blinn. 纹理贴图是一个用图像、函数或其它数据源来改变表面在每一处的外观的过程。 例如,我们不必用精确的几何去表现一块砖墙,而只需把一幅砖墙的图像贴到一个多边形上。
E N D
Chapter 5. Texturing纹理贴图 金小刚 Email: jin@cad.zju.edu.cn http://www.cad.zju.edu.cn/home/jin 浙江大学CAD&CG国家重点实验室
“All it takes is for the rendered image to look right” —— Jim Blinn • 纹理贴图是一个用图像、函数或其它数据源来改变表面在每一处的外观的过程。 • 例如,我们不必用精确的几何去表现一块砖墙,而只需把一幅砖墙的图像贴到一个多边形上。 • 除非观察者非常靠近墙,否则我们并不会觉得缺少几何细节(例如发现砖头和泥浆在同一表面上)。 • 既节省了大量的造型工作量,也节省了内存空间,加快了绘制速度。
并非由于缺少几何细节的缺陷…… • 但是,贴了纹理的砖墙还会出现并非由于缺少几何细节而出现的不真实的缺陷。 • 但是:砖是发亮的(shiny),但是泥浆不是。但我们会发现砖和泥浆同样发亮。为了生成更真实的效果,我们还需要一张镜面高光纹理贴图。 • 但是:砖不是平的,其表面通常是粗糙的。我们还需要凹凸纹理(Bump mapping)
计算物体 空间位置 用投影函 数计算(u,v) 用对应函 数找到纹素 应用值 变换函数 改变方程或 Fragment值 广义纹理贴图(Generalized Texturing) • 纹理贴图可看成是一种有效的改变物体表面属性的一种方法。颜色、高光、凹凸、反射、透明度等等都可采用纹理贴图。 • 从贴图图像中取出相应的值代入光亮度计算方程。 单个纹理的广义贴图流水线。 采用该复杂流水线的原因:每一步都可给用户提供有用的控制
投影函数(Projection function) • 投影函数把三维空间点转化为纹理坐标。 • 常用的投影函数:Spherical, Cylindrical, Planar Projections, 参数曲面的(u,v)映射 • 其它:如根据表面法向来确定6个平面投影方向
不同的纹理投影 spherical cylindrical planar (u,v) 应用 应用 应用
即时(on the fly)投影 • 在实时绘制中,投影函数常常在造型阶段应用,然后把纹理坐标记录在顶点上。 • 也可即使计算:如OpenGL的glTexGen函数可提供不同的投影函数,然后让图形加速卡即时计算投影。 • On the fly投影的优点:纹理坐标不需要送到图形卡,节约传输带宽。
纹理投影时会带来畸变,艺术家经常通过人工交互方法把模型分解成接近平面的碎片。纹理投影时会带来畸变,艺术家经常通过人工交互方法把模型分解成接近平面的碎片。 多个小纹理拼成的大纹理(雕塑模型) 多边形网格模型在纹理空间的展开
纹理坐标的形式 • 纹理坐标有时表示成三个坐标(u, v, w)的形式,其中w为投影方向的深度。如医学图像数据。 • 有些系统把纹理坐标表示成四个坐标(s, t, r , q)的形式,其中q为齐次坐标,可用于聚光灯效果。 • 每个纹理映射可以有自己的纹理坐标 (Muti-texturing)
对应函数(Corresponder Function) • 对应函数把参数空间的值转化为纹理空间的位置。 • 第一种对应函数: 用API选择一部分纹理(子纹理)进行纹理映射。 • 另一种对应函数:用矩阵变换。由于OpenGL支持4X4矩阵操作,任何API的应用层都可采用这类变换,如平移、旋转、比例变换、错切等
超出[0,1)纹理空间怎么办? • 对应函数还控制纹理空间超出[0,1)时的处理方式 • OpenGL中这类对应函数称为“wrapping mode” • Direct3D中这类对应函数称为“texture addressing mode”
处理上述问题的常用对应函数 • wrap (DirecX), repeat (OpenGL), or tile: 纹理图像在表面重复。例子:地上的大理石贴图 • mirror: 纹理图像在表面重复, 但每隔一幅进行翻转(flipped)。这样在纹理的边界处,纹理可以保持连续。 • clamp (DirectX) or clamp to edge (OpenGL): 把[0,1)范围之外的进行截断。截断到[0,1)内的半个纹素。 • border (DirectX) or clamp to border (OpenGL):参数范围在[0,1) 之外的用单独定义的边界颜色或把纹理的边作为边界。用于在表面上印花样,地形绘制中相邻纹理的缝合。截断到[0,1)外的半个纹素。
例子 repeat mirror clamp border
实时绘制中隐含的对应函数 • 根据纹理图像的大小,隐含的对应函数把(u, v)映射到纹理图像的纹素(texel)位置。 • 采用(u, v)的好处在于,对于不同分辨率的纹理图像,其存贮在顶点处的(u, v)值是相同的。即使改变纹理图像的大小,其(u, v)值不需要改变。
三维纹理 • 三维纹理的优点是可以避免二维纹理中可能出现的畸变和接缝问题。如木纹、大理石纹理等。 • 三维纹理的合成方法:噪声函数。由于计算噪声函数的代价,通常预先算好空间Lattice点的值,其它地方进行插值。
Combine Function or Texture Blending Operations 大部分实时系统允许用户选择纹理和表面粘合方式,这些方法称为Combine Function 或 Texture Blending Operations: • Replace: 把原来表面的颜色替换为纹理的颜色 • Decal(印花):与替换类似,但是若纹理中包含Alpha值,则用它与表面的颜色进行混合。 • Modulate(调节):把表面的颜色与纹理颜色相乘
Image Texturing • 在硬件图形加速卡中,纹理图像的大小经常为2m×2n(或者2m×2m)的纹素,其中m和n为非负整数。不同的图形卡有不同的纹理大小上限。 • 若投影得到的象素数目比原始纹理大,则需要把纹理图像放大(magnification); • 若投影得到的象素数目比原始纹理小,则需要把纹理图像缩小(minification);
纹理放大 一幅32×64的纹理应用到一矩形,非常近看。 左图采用最近领域滤波,即对每个象素选择最近的纹素。 右图采用最近四个纹素的双线性插值 锯齿状消失,质量好 块状效果明显,质量差
纹理缩小 • 当纹理图像缩小时,多个纹素可能覆盖一个象素单元。为了得到每个象素正确的颜色,应该综合考虑影响该象素的那些纹素。 棋盘格纹理多边形通过一行象素,显示多个纹素可影响单个象素
实时系统中的解决方法 1. 点采样(Nearest neighbor) 2. Mipmapping 3. 求和面积表(summed area table)
最近邻域法:选择在象素中心可见的纹素。但会引起严重的走样现象,见上图。当这类表面相对视点移动时,走样现象更加明显,称为时间走样 (temporal aliasing) 。 • 双线性插值:效果仅比最近邻域法稍好,也会引起较严重的走样现象。 • 纹理反走样算法的基本思想:对纹理进行预处理,建立多个纹素覆盖单个象素的快速逼近计算的数据结构。这样,一个采样点可以检索出一个或多个纹素的效果。 在实时绘制应用中,这些算法在执行时具有固定的时间和资源。
Mipmapping • Mipmapping是纹理反走样最受欢迎的方法。目前,很多图形加速卡支持该功能。 • Mip: 表示multum in parvo, 拉丁语的意思是“很多东西在一个小的地方”。 • 思想:在绘制之前,把原始纹理图像进行重复滤波,生成多幅小纹理图像。
1/16 Level 2 金字塔结构 1/4 Level 1 1 Level 0 d轴 downsample直到子纹理的任一维为一个纹素为止
构造高质量Mipmap的两个重要元素 • 好的滤波。常用方法为把2×2的象素进行平均得到Mip值。但因采用的是Box滤波,可能是最差的滤波器,会导致较差的结果(走样)。较好的滤波器:Gaussian, Lanczos, Kaiser。 • Gamma校正:如果忽视Gamma校正,会导致得到的Mipmap纹理图像的亮度与原始图像不同。
如何检索Mipmap结构 一个屏幕象素覆盖了纹理的一块区域。为了检索,我们需要找出大致多少纹素影响该象素。
主要有两种方法计算d(OpenGL中称为γ,也称为层次细节) : 1。采用由象素单元构成四边形的长边 2。采用四个偏导 中绝对值的最大值进行度量。每个偏导表示纹理坐标相对于屏幕坐标变化量的度量 由于Mipmapping是硬件支持的一个标准项,具体计算方法可参考相关参考书。
计算坐标d的目的是为了决定在mipmap金字塔轴采样的位置。通过三元组(u, v, d)来检索mipmap • d的意义类似于纹理层。 d不是一个整数,其分数部分表示对应象素到纹理层 的距离。我们对纹理层 和 进行采样。 • 先用(u, v)对纹理层 和 进行双线性插值采样, 然后再用d- 对这两个采样值进行线性插值。整个过程称为三线性插值。
Mipmap检索中的控制参数 • 在d坐标上的一个控制参数为Level of Detail Bias (LOD Bias)。该偏移量加到d值上,用来影响纹理的精锐度(sharpness)。 • 如果我们把d坐标沿着金字塔轴往上移,则纹理看起来更模糊一些。根据纹理的类型和应用的需要,我们可以选择不同的偏移量。 • 当图像看起来较模糊时,可选择负的偏移量;当图像走样较严重时,可选择正的偏移量。通常,当贴了纹理的表面在移动时,应选择较大的偏移量以避免时间走样。
Mipmap的缺陷… • 过于模糊现象(overblurring): 假设象素单元在v 方向覆盖很多纹素,但u方向覆盖的纹素很少(这在我们沿着边看一个贴了纹理的表面时经常发生)。甚至,应该是一个方向放大,另一个方向缩小。但在Mipmap中得到的是正方形纹理区域,而不可能得到长方形纹理区域,而我们选择的是最长边,故结果看起来过于模糊。
Ripmapping • 克服过于模糊现象的一个方法是Ripmapping(HP公司用的词)。其原理是把mipmap的思想推广,允许长方形区域进行下采样。 • 采用四个坐标检索纹素: (u, v)用来检索子纹理,其它两个用来检索Ripmap数组。 • 需要用四个子纹理进行插值。
Ripmap结构 从左下角到右上角的对角线子纹理构成mipmap子纹理
求和面积表(Summed-Area Table) • 首先建立一个与纹理大小相同的数组,但其包含的颜色的位数精度更高(例如,红、绿、篮分量的位数为16bits或者更高)。 • 在数组的每个位置中,计算并存贮由相应纹素和纹素(0,0)构成的矩形区域内的所有纹素的和。 • 在纹理贴图时,象素单元在纹理空间的投影由一矩形构成。通过读取求和面积表的数据来决定该矩形的平均颜色,并把该颜色作为象素单元的纹理颜色。
计算公式解释 • x和y分别为矩形的纹素坐标,s[x ,y]为相应纹素的求和面积表的值。 • 分子为包围盒内纹素的和, 分母为包围盒面积。
效果… Mipmap 靠近地平线的直线变的比Mipmap尖锐 求和面积表 但在对角交叉线的中间仍然模糊(同样的问题ripmap也存在), 这是因为当纹理对角看时,产生了一个大矩形,很多不被象素单元覆盖的纹素也一并被计算进去。
讨论 • Ripmap和求和面积表属于各向异性滤波( anisotropic filtering)。 能够检索非正方形区域的纹素值,对接近水平和垂直的方向最有效。 • Ripmap用于1990年代HP公司的高端图形加速卡 • 求和面积表还未见硬件实现。 • Ripmap和求和面积表都比较耗内存。Mipmap的子纹理只需耗原纹理大小的1/3, 而Ripmap为原纹理大小的3倍,求和面积表至少1倍(精度越高,所需存贮越大) • 纹理内存比较昂贵,不能随便浪费。
无约束各向异性滤波(unconstrained anisotropic filtering) • 对于当前的图形硬件,进一步改进纹理滤波的最常用方法为重用已有的Mipmap硬件。 • 思路:把象素单元在纹理空间投影的四边形采样多次,然后把采样点加权平均。不用单个Mipmap采样去逼近四边形的覆盖,而是用多个正方形去覆盖四边形。 • 四边形的短边用来决定d(Mipmap中用的是长边), 使得Mipmap采样点中平均的面积变小, 从而变得不模糊些。 • 四边形的长边用来创建一条与长边平行并且经过四边形中心的各向异性直线。
当各向异性比为1:1到2:1之间时,采样两个点。各向异性比越大,则沿轴的采样点越多。当各向异性比为1:1到2:1之间时,采样两个点。各向异性比越大,则沿轴的采样点越多。
上述机制允许各向异性直线朝任意方向,而不像ripmap和求和面积表那样有限制(水平或垂直)。上述机制允许各向异性直线朝任意方向,而不像ripmap和求和面积表那样有限制(水平或垂直)。 • 除Mipmap的纹理内存外,不需要额外的纹理内存。 • 如果图形卡支持双通道体系结构(允许并行获得两个Mipmap采样),则能实时实现2:1各向异性滤波。支持的通道越多,则可用的最大各向异性比越大。 • NIVIDIA Geforce3:支持8:1各向异性滤波。 • ATI Radeon 8500:只有在象素单元在纹理空间的投影接近垂直或水平时才执行各向异性滤波。
无约束各向异性滤波例子 Mipmap vs. 各向异性滤波 左图为三线性Mipmap, 右图为16:1各向异性滤波,分辨率为640×450,采用ATI Radeon硬件。在接近水平线的地方,各向异性滤波提供了更尖锐的结果、最小的走样
纹理高速缓存(Texture Caching)和压缩 • 复杂的应用需要相当多的纹理。快速纹理内存的大小与系统有关,但一般的原则时永远不会够。 • 有多种纹理高速缓存技术: 在速度和内存中的纹理数目之间取得平衡。例如:当贴了纹理的多边形离视点较远时,可只载入需要的子纹理。 • 每个系统有它自己的纹理管理工具和性能特点
使用纹理内存的一般原则 • 尽量使纹理小:不要大于使得纹理需要放大。 • 尽量使得使用相同纹理的多边形成组。 • 采用Tiling或者Mosaicing技术:把一些小纹理拼成一块大纹理,这样可以避免纹理的切换,加快存取的速度。
最少使用(Least Recently Used)策略LRU • 把载入图形加速卡内存的纹理设置一上次存取的时间标记。 • 当需要上载新的纹理时,先卸载具有最老时间标记的纹理。 • DirectX和OpenGL还允许对纹理设置优先级:当两个纹理的时间标记相同时,具有较低优先级的纹理先卸载。从而避免不必要的纹理交换。
Prefetching方法 • 上载一幅纹理需要不少时间。在需求驱动的系统中,一幅纹理只有在它所对应的多边形在视域之内时才上载,每帧所需的纹理数目可能相差非常大。若需要在单帧内上载大量纹理,难以保持恒定的帧率。 • 一个解决方法:采用预取(Prefetching)方法。通过预测将来需要的纹理,并预先上载。
Clipmap方法 • 在飞行仿真和地理信息系统中,图像数据库可能非常庞大。传统方法为把大图像分成小块图像(tiles),使得硬件能够处理。 • Tanner提出了一种称为Clipmap的数据结构。其原理是把整个数据库看成一Mipmap,但在任何一个特定的视域,只有一小部分低层次的Mipmap是需要的。 • 根据视域对Mipmap结构进行裁剪,得到所需要的部分。
Clipmap例子 通过存取一庞大的图像数据库来进行高分辨率地形纹理贴图。通过clipmap减少一次所需的数据量。