赞
踩
纹理就是一张图,将其贴在三维物体。
纹理映射(Texture Mapping),又称纹理贴图,是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程。简单来说,就是把一幅图像贴到三维物体的表面上来增强真实感。
任意三角形的顶点都能找到顶点在纹理上哪个位置。
不管长宽比和分辨率,U和V的范围都在0到1内。三角形的三个顶点,每个顶点都对应一个UV。
纹理能被多次使用。如果纹理重复上下左右可以无缝衔接,则称这个纹理是tiled textures。(有一种算法叫Wang tiling)
知道了三角形的三个顶点的UV坐标,如何得出三角形内部的UV坐标,引出三角形的插值。
如果对三角形的三个顶点都有特定的值,可以得到三角形内任何一点的这个值,并且这些值从一个顶点到另一个顶点是平滑过渡的。
插值的对象?
纹理坐标,颜色,法线向量…
插值的方法?
重心坐标
重心坐标是定义在三角形上的,在重心坐标系中,三角形平面的任何一个点(x,y)都可以表示成三角形三个顶点的线性组合(系数分别是α β γ ,且满足这三个系数相加和为1)。如果这个点在三角形内,则需要α β γ都是非负的。
例如:
A点的重心坐标( α , β , γ ) = ( 1 , 0 , 0 )且(x,y)=αA+βB+γC=A
重心的性质:将重心与三个顶点相连,可以把三角形分割成等面积的三个三角形。下面是重心坐标系和普通坐标系下的三角形重心坐标。
可以通过面积比求重心坐标。α,β,γ的计算如下所示,其中A点对应A A(表示A点的面积),B点对于BB,C点对于CC
然后通过叉积求面积,得到重心坐标的一般的表达式。
对于每一个光栅化的样本(x,y)的应用流程如下:
假设一张 480 * 270 尺寸的纹理要铺满渲染到分辨率为 1920 * 1080 的屏幕上,此时一个纹素的大小可以理解为是像素的4倍,多个像素点对应一个纹理坐标。
对于任何一个点找到纹理上的位置,如果纹理上的这个位置不是整数,采用四舍五入的办法变成整数。这样的话在一定范围内查找的是相同的纹理上的像素(texel 称为纹理元素、纹素 )。
纹理太小会出现一块一块的效果,没有平滑的过渡。
如图中红色点是屏幕空间下一像素所对应在纹理空间中的点,会去采样离他最近的那个纹理颜色点,这种近似采样方法是不可取的。
首先取出离红色点最近的4个黑色顶点,分别算出,该红色点在水平及竖直方向偏移的比率s,t,如下图所示。
水平方向插值得u0和u1,竖直方向插值得结果:
除了双线性插值外,还可以使用双三次插值(Bicubic Interpolation),取的是周围16个像素而非4个像素(非线性),虽然效果好但是带来的弊端就是开销会很大。
如果纹理过大会出现更加严重的走样,远处摩尔纹,近处锯齿。
由于近大远小的透视关系,对于一个像素来说,近处覆盖的纹理区域相对较小,许多个采样点对应了同一个纹理颜色;而远处覆盖的纹理区域则很大,用一个点的采样无法代表一大块纹理区域的颜色变化。
这种屏幕像素对纹理贴图的覆盖区域,被形象的称为屏幕像素在纹理空间的footprint。
屏幕上的像素从近到远,一个像素覆盖纹理上的区域是由少到多的。
但是对于很远的点,一个像素的颜色值以一个中心点来采样是相当不准确的。
其实道理类似,纹理过大,每个纹素的大小相较于像素更小了,就导致每个像素覆盖的区域实际上会包含多个纹素,但在片元着色阶段只会进行一次点采样,得到的结果显然是不够“精密”的。从信号学的角度上来理解,每个像素的采样频率远远低于纹理上的变化频率,于是也会形成锯齿的效果。假设一张特别大的纹理贴在地面上,由于透视摄像机的近大远小原理,会放大像素与纹素的信号频率差距,因此远处的地面会形成一种叫做“摩尔纹”的效果。
对于锯齿的效果,上面说过可以采用双线性插值方法修复,通过插值平滑的过渡;对于摩尔纹,由于采样点不足,采样的速度跟不上信号变化的速度,可以采用超采样方式,增加采样点,例如几百倍的超采样,显然可以解决问题,但是付出的代价是极为高昂的计算成本,显然不可取。
解决方法:避免采样,不采样,快速获得一片区域的平均值,范围查询。
允许进行不同大小的范围查询。(快速的正方形的近似范围查询fast、approx.、square)
Mipmap是一种典型的空间换时间的解决方案,通过「范围查询」来替代之前双线性差值所做的「点查询」,它的好处就是速度快,但是也有缺点:结果不够准确、只能用于正方形(2的幂次方)贴图,以及增加了额外的存储量(增量约为1/3)。
Mip意思是很多不同的小东西。
对于一张贴图,可以不断将分辨率缩小一半。
然后只需要找出每个像素在对应层对应位置的映射就可以了。
如下图是Mipmap可视化,可以发现有渐变,但是渐变不连续。
当计算出的层数恰好不是整数的时候(事实上经常会出现这种情况),同一纹理上的不同Mip之间会出现明显的断层现象,如下图底部的红色区域,深红色直接过渡到鲜红色,十分地不自然。
出现了这种不自然的过渡,解决办法依然是老办法:「差值」 !
三线性插值即两次查询,一次插值,找到D和D+1层的结果然后进行插值。
经过三线性插值后的Mipmap可视化
出现了Overblur(远处模糊的过分了)
原因:只能对正方形进行近似,插值不是精确而是近似值。Mipmap只能针对正方形纹理进行Mip分层,当透视效果越明显,越远处的像素对应纹理中的区域会越不接近正方形(更像长条的矩形,甚至连矩形都不是),如果使用面积更大的正方形来包住这个区域,此时的结果就会愈加不准确,造成了越远处越模糊的感觉。
产生上面这种现象的原因是因为,所采用的不同level的Mipmap默认的都是正方形区域的采样,然而真实情况并不是如此,见下图:
可以看出不同屏幕空间的像素点所对应的footprint是不同的,有长方形,甚至是不规则图形,那么针对这种情况,有的需要水平方向的高level,有的需要竖直方向上的高level,因此也就出现了各向异性的
各向异性可以用不同的长宽比进行缩小,也就是可以用矩形区域做范围查询,而代价就是消耗更多的存储。
利用这样不同比例的Mipmap贴图,结果就会明显好很多:
对于不规则的形状可以拆成几个圆形去覆盖这个形状。每次查询一个圆形,然后多次查询来覆盖不规则的形状。
在现代的GPU中, texture = memory + range query,texture是一块数据可以做各种不同的查询。可以定义不同的属性,不限定为颜色,如高度、法线等向量信息
如下茶壶会被环境光照亮,即它可以反射出任何方向来的光。如下图就反射出了窗户和门
可以把环境光记录到球上,并且展开。
展开后出现了扭曲问题(向中间扭曲)
解决办法 —— Cube Map
即不把光照信息存在球的表面上,而是立方体的表面。
因为立方体各个面是均匀的,所以不会出现扭曲。
存在的问题:相对于球来说,需要多记录一个方向。
本质:记录不同方向的光照信息。
纹理可以定义任何不同位置任意不同的属性,比如定义任何一个点的相对高度。
如下图就是一种凹凸贴图(定义法线的不同),这样就可以不用定义复杂的几何形体。
Normal Mapping法线贴图不等于Bump Mapping凹凸贴图,法线贴图存储的是法线,凹凸贴图存储的是高度差。
凹凸贴图可以定义复杂的纹理,但是不改变任何几何信息(三角形数量不变)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。