首页 > Unity3D频道 > 【NGUI研究院之Unity插件】 > NGUI研究院之与图片拼接的1像素接缝(十六)
2014
08-21

NGUI研究院之与图片拼接的1像素接缝(十六)

如下图所示美术给我两张255X255的图片让我来拼接。第二张图的X坐标明明是X偏移255的为什么中间有一像素呢?

NGUI研究院之与图片拼接的1像素接缝(十六) - 雨松MOMO程序研究院 - 1

 

此时如果你不加思索的就把X偏移改成254。仔细看看下面这个位置明显图片没有被拼接上?如果两张图片都是纯色的话可能这样可以被拼上,但是这是不解决核心问题的。。

NGUI研究院之与图片拼接的1像素接缝(十六) - 雨松MOMO程序研究院 - 2

 

如果你看NGUI的源码你会发现NGUI会自动把奇数宽高的图片补起成偶数的宽高图片。如下图所示,当你制作完一个NGUI的图集后你会发现NGUI自动打开了MipMaps 并且利用三线性来过滤图片。

NGUI研究院之与图片拼接的1像素接缝(十六) - 雨松MOMO程序研究院 - 3

 

如下图所示,如果你把混合模式改成点线性过滤,你会发现你的图片拼接的非常OK了。

NGUI研究院之与图片拼接的1像素接缝(十六) - 雨松MOMO程序研究院 - 4

 

从效率上来说 点线性过滤 > 二线性过滤 > 三线性过滤。如果点线性过滤好用的话为什么NGUI要用三线性过滤呢?

1.UISprite是可以随便缩放的,如果不缩放的话点线性没问题,可是一旦缩放因为用点像素来填充那么图片必然糙了。。

2.我觉得NGUI是为了支持3D界面所以不得不在生成Atlas后时候勾上了Generate Mip Maps选择三线性来过滤图片。生成MipMaps以后那么在内存中的图片会大很多(MipMaps就是典型的用空间来换时间)所以如果你没有3D界面的话一定要把mipMaps关闭,采取二线性过滤即可。

最后在回到文章的题目,如何解决NGUI图片的拼接问题。

1.不要用奇数图片,保持美术给的图宽高都是偶数。

2.拼接的时候都按偶数像素来拼接。

3.取消Generate Mip Maps ,不生成MipMaps。

4.图片采用点线性过滤模式。

5.采取点线性过滤的话图集上的图片就不能使用NGU的缩放功能了,不然图片会糙的。我觉得可以把需要拼接的图片放在一个图集上,如果拼接的图片不多的话也可以考虑用UITexture 。

这样问题就可以完美的解决。如下图所示,图片完美的拼接了。。

NGUI研究院之与图片拼接的1像素接缝(十六) - 雨松MOMO程序研究院 - 5

我对OpenGL 底层了解的也不多, 希望大家大家在留言处留下宝贵的意见。也算给我指点指点,谢谢。

雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!

--

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。

  1. 文章里面有一处说得不正确,mipmap不是使用空间换时间的,而是为了解决采样不稳定的问题,例子就是斜着观察棋盘,远处会出现采错误。

  2. MOMO,NGUI中UISprite、UITexure、UI2DSprite等类里的drawingDimensions属性里有if ((w & 1) != 0) ++padRight;if ((h & 1) != 0) ++padTop;这么两句,请问为什么要这么做?还有MakePixelPerfect函数,为什么结果也非要强制偶数?

  3. 松哥,我用UGUI做2D像素游戏,地图图片设置为point(点线性过滤),但是图片移动的时候回有花纹装效果(帧率稳定,摄像机不动)请问有什么解决办法吗?

  4. 刚发现这问题确实是两种情况,我以前是用UITexture的时候碰到这条线,这种情况就是Wrap Mode改为Clamp就能解决;另一种情况是用图集的UISprite,这时改Wrap Mode就没用了,只能Filter Mode改为Point解决,但是图片会变得颗粒感很强,还是得尽量避免= =

  5. 至于奇数尺寸的图片,只要其实无关黑线,组件snap之后虽然尺寸是偶数,但只是在右边和下边空出一个像素,移动一下位置就行。

  6. 其实产生黑线的原因就是因为非点线性过滤模式。图片的边缘像素会与周围像素做一定程度的均匀采样,而NGUI做成的图集的空隙处,是用颜色(0,0,0,0)来填充的,被均匀采样的像素会因为空隙的黑色透明而比原来的颜色更暗更透明,所以出现了黑线。所以不只是拼接而成的图片,单张图片也会产生黑边。我的做法是利用为了九宫格图片而设置的border,修改UIBasicSprite的填充函数,增加一个是否渲染边缘(周围8块)的选项,如果不渲染,则不生成边缘的8块mesh的顶点数据。当然,如果需要用到slice模式,只能让美术给图片边缘扩充1-2个像素,颜色与原边缘像素相同。(因为美术太懒,我都是自己PS的……)我还给UIBasicSprite增加了镜像复制的功能,这样我只需要一个角,就能得到一个矩形,当然,用于镜像方向的边界,也是去掉border那么多的像素的。

  7. 这种方法只能用在 Pixel Perfect 的情况下使用,如果图片有缩放那么还是会产生缝隙,而且因为采用了 Point 采样还会导致图片模糊问题。正确的做法是让美术在 Maya 里面制作一个背景,或者动态生成一个mesh,动态设置uv坐标。 总之,使用多个 mesh 之间肯定会产生缝隙。

  8. MOMO,用NGUI做3D界面,project settings -> Quality -> Anti Aliasing -> 8X ,但斜边边缘还是会有抗锯齿。如果设置Texture Quality为half res,抗锯齿的问题就解决了,可是图片就变得模糊。有什么好的解决方案吗

  9. MOMO,我按照你的方法,放上去的确没有缝隙里· · 但是我的是一张可以拖拽的地图 拼接;当我拖拽的时候,缝隙就出现了···MOMO大神,这是何解 ? 渲染不对了 ?

  10. 请教下momo,我用新版ngui设置的动态字体,但是在UIlabel中设置fontsize改小时发现没变小,而是变虚了,以前老版ngui好像没这个问题,请问您知道是怎么回事么?谢谢

  11. 我用你的方法试了,改成point,那条线确实是没有了,但是图集里面的其他图片(没有拉伸的图片)全部都很粗糙了,这个怎么弄?改回三线性过滤后图片是不粗糙了但是那条线又出现了

  12. 雨松前辈,在CEGUI和MyGUI里面都有层次管理的概念,而NGUI则通过Depth来管理窗口间的层次,但这样不太方便,举个例子:子panel不一定在父Panel前面,仅由它们的Depth决定。你有没遇到过相关问题,或者有没比较好的层次解决方案?

  13. 不知道我出现的问题和你的是否一样。美术给了一张过大的图,拆成两张,贴到两个片上放一起中间会有一条线,和你第一张截图表现一样。我是把两张图片的Wrap Mode改为Clamp就能解决这个问题。因为默认是Repeat,就是使用自身循环来补齐像素,这相当于在我们已经结合好的图里加了东西(那条线);而Clamp是拉伸,就不会出现那条线了。不知道我的理解对不对。我在改变Filter Mode的时候对这条线没有影响,而是选择Point的时候是图片近看后出现了像素感,线性过渡的话就比较平滑,没有像素感。