运行时黑边/白边/毛边修复方案

项目在使用2.4.4开发的过程中,发现在打包安卓原生后龙骨动画在肢体的拼接处会产生黑边的情况
黑线
开启了alpha预乘选项后毛边消失,但后来在安卓上对纹理应用ETC2压缩后alpha预乘就不能再用了,否则带透明度的图片alpha通道的值都会出问题,无奈关掉后黑线又出现了。

在翻阅了论坛中大量的图片的黑边毛边问题相关的讨论后,尝试使用Filter.NEAREST过滤器对龙骨纹理进行采样,结果虽然黑线消失了但边缘锯齿感严重,最后寄希望于图片扩边。


在这个讨论中有大佬分享了自己的扩边程序,实际使用后黑边消失但带来了白边,此方案还不是那么完美。在此为cocos证明,黑白毛边等问题不是cocos才有的问题,正如这个讨论中有人提到的这是个由来已久的问题,在unity论坛和Stack Overflow都能搜索到大量的讨论,产生黑白边的原因简单来说是在某些情况下,比如不同的设备分辨率或者不同的显示尺寸,GPU对纹理采样时会将周边的纹素值一并采样并插值以获得平滑的效果减少最终呈现出来的锯齿感。
举个例子
QQ图片20220827142505
这是一张龙骨的肢体图灰度化后的结果,在这张图片中圈出来的部分是肢体的拼接处,也就是上图出现黑线的地方,对于美术同学给出来的图来说是没有什么问题的,图片边缘的颜色能正常衔接到肢体上,并且没有任何杂色。但实际因为肢体边缘外的像素RGB值均为0,采样时如果用到了这部分像素做插值,必然导致插值后的RGB值降低,黑边由此产生。但不可能要求每个图都让美术在附近补充临近颜色的像素点,所以需要用程序化的方案去批处理所有图片。(photoShop貌似有插件也能解决问题,但不在程序的考虑范畴内)

最终我的修复方案如下,对原图做一次均值模糊进行扩边生成一张扩边图,然后用扩边图覆盖掉原图上透明度为0的所有像素,这些像素的alpha还是保持为0 ,这样就能将原图的边缘扩充出去。并且边缘是用的均值模糊的结果做的扩边,可以尽可能的贴近边缘的RGB值,防止出现单一色的白边等问题。

将修复后的图片灰度化后可以看到像素已经向外扩充一圈
Snipaste_2022-08-27_14-25-36
但实际用图片浏览工具打开图片跟原图看是一模一样
Snipaste_2022-08-27_14-54-08
因为这些扩充出去的区域alpha值为0,我们并不想让这块扩充区域真正的渲染出来,只要在GPU采样边缘附近像素的时候能取到跟边缘相近的RGB的值就行了。

最终实际打包后运行黑线几乎消失(图片已被放大N倍后只能看到一点点痕迹,实际运行效果看不出接缝处有异常),问题解决
修复

6赞

链接: https://pan.baidu.com/s/1SFIHp1kXDtbjxLfbKxpGwg 提取码: iyr8
解压后命令行运行
./texelExt.exe xxxx.png
会在png所在的文件夹下创建一个带_modified后缀的新png文件。新文件会比源文件大一些是正常的,因为像素被扩充了

6赞

如有问题欢迎指正,如有更好的解决方案,欢迎各位大佬分享

1赞

感谢分享!!

牛批

牛逼,解决了多年的困惑