话说在之前GeoGlobe的瓦片与瓦片之间貌似出现了很多的“裂缝”,乍一看我的心就凉了,好不容易贴出来的图怎么就是这个效果呢?
静下来细细想想,初始印象就是无非有两种情况:
1、纹理映射的坐标对应关系有问题,亦即纹理贴图没有对应于正确的模型上的实际坐标。这个是有可能的,记得去年暑假的时候,就是由于在精度的上的很小差异(近裁剪面的double和float之争),所以在视景体计算结果导致的那个天壤地别啊。而这里是先将全球格网等分映射然后换算成曲面,那么之间会不会出了问题?
2、数据有问题,有想过,师兄也建议我检查下。但是这里出问题的可能性不大,别人贴的都没问题,难道到我这就出问题的?
接下来我赶紧调啊调,不断在瓦片与瓦片之间跟踪数据。可是结果证明数据是没有问题的啊,经纬度是同样规则划分的,即使在转换成曲面出现误差,这个误差瓦片瓦片间都是有的,所以这个应该不是数据的问题。数据最后检查也没有问题的。那么究竟哪里出了问题了呢?
是在走不下去了,我分析可能是我的问题根源找的不够细致。我又重新看了下那些“裂缝”,到纹理的细部去看看,到底出了什么问题,果然有所发现:
在下面两幅图中,有些有“裂缝”,有些却没有,而且给人的直观印象就是,“裂缝”的产生是由于隔壁瓦片好像影像了它衬在下面一样。难道贴上去的纹理发生了重叠?那为什么会发生重叠呢,难道是纹理映射的时候哪里设置不对出了问题?
为此,我又重新看了下纹理映射的原理,上网查阅了不少纹理映射的资料。最后在一个貌似不起眼的位置好像看出了一些端倪---纹理寻址模式。
纹理源图像的像素点都用纹理坐标系的[0, 1] x [0, 1]范围内的坐标来量度,如果选定的顶点纹理坐标u和v大于1或小于0时,那么对应的纹理像素点在纹理源图上是不存在的。因此为了确保模型“有图可贴”,需要用相应的纹理地址模式来寻址,确定该顶点颜色值应该采用的纹理像素颜色值。由此可见,当选定的待渲染三角形面顶点的纹理坐标超出[0, 1]区间时,可获得一些特别的渲染效果。
对于Direct3D,它定义了4种纹理寻址模式来处理纹理坐标超出[0, 1]范围的纹理映射方法,分别是重叠映射寻址(wrap)、镜像纹理寻址(mirror)、夹取纹理寻址(clamp)、边框纹理寻址(border)。OpenGL也是做的类似处理,目的就是为了当指定纹理坐标时出现的一些异常情况。而Ogre是对Direct3D和OpenGL高一层次的封装,所以沿用了这一特点。
利用一个小Demo可以看到这几个模式的明显区别:
我查了下,重叠纹理寻址(wrap)是Direct3D中缺省的寻址模式(也是哦,应该的),也是三维系统中最常用的寻址模式之一。试想想,在渲染具有诸如砖墙之类纹理的物体时,只会包含一整张砖墙的纹理贴图,但是重复加载使用会占用较多的内存,所以这种模式通常只需载入一张具有一块或多块砖瓦的较小的纹理贴图,再把它按照重叠纹理寻址模式在物体表面映射多次,就可以达到和使用整张砖墙贴图同样的效果。那么Ogre自然也就沿用了这一模式为默认,当然这种对于单一贴图重复使用真的很有效,但是对于不需要这种效果的来说,可能就是会致命的。但是我试了下,边框纹理寻址(border)也不好使,那个边界效果可是更明显了,没有“裂缝”也能生生扯出“裂缝”来。最后只有夹取纹理寻址(clamp)、镜像纹理寻址(mirror)好使,不过夹取纹理寻址(clamp)给人的感觉好像是一种专门为不同纹理之间设计的,中间貌似是一个平滑的处理(只是yy)。所以果断选择了这种模式,最后贴出来的效果就好多了