对于3D模型涂色的核心思路我的构想是找到屏幕触摸的点在3D模型上的位置,然后找到UV,接着根据UV在3D模型的贴图上修改RGBA值,达到涂色的目的。而阿杰发给我的Demo里的思路也和我预期的差不多。但是我在这个Demo里发现了一个RenderTexture,这不由得让我心生疑惑。
这个解决方案里怎么会有RenderTexture出场的地方呢?于是我就借助AI研究了一下这个代码。这不由得让我心头一震。当前的场景里有一个3D的狗狗模型,这个就是要涂色的地方。但是在Canvas上故意放了一个在场景之外的正方形精灵,精灵使用的图片就是这个狗狗的纹理贴图。它的思路是将涂色的RGBA值放到一个单独的buffer里。然后每帧用第二个摄像机去拍摄这个正方形精灵,将得到的内容输入到一个RenderTexture里。然后再将之前提到的Buffer二次填充到RenderTexture里,最后将这个RenderTexture赋值到狗狗模型的材质上。
这不是绕了一个超大的远路了嘛?我琢磨了一下,这个demo之所以这么做,是因为还有一个橡皮擦的功能,可以将涂色的部分擦除掉。它保留一个RenderTexture其实就是保留一个原始的纹理,方便后边擦除使用。虽然如此,这个思路也是太搞笑了。我直接删除了这个RenderTexture相关的逻辑,然后做了如下修改,将图片原始rgba值,保留到originBuffer里,作为备份。然后直接拷贝一份作为上模型的buffer。每次涂色都是直接操作上模型的buffer,然后upload给Texture2D。如果需要擦除就从originBuffer获取到原始的颜色覆盖回来就行。
这样子确实可以提升一些性能。不过还是不够的。现在是每一个touchMove里都会做 获取涂色点->修改上模型的buffer->upload到Texture上。我认为完全没有必要每一个touchMove都做一遍这几个耗时的操作。为此我继续做了优化。
涂色Interval作为一个时间阈值,只有超过这个时间间隔才会做获取涂色点->修改上模型的buffer的操作。比如我设置为1/60。那么就是每隔1/60秒才会做一个涂色修改buffer的操作。这个值设置的越大,那么涂色的连贯性就会越差,出现没有连成线,而是连成点的感觉。
上传纹理Interval作为一个时间阈值,用来表示每隔多少秒才会调用一次Texture的upload函数。比如我设置为1/10。那么就是会将6次涂色的buffer合并为一次才上传到Texture上。这个值越大,则越不跟手。表现为手指划过去了后颜色出现要等1/10秒才行。
接着是原始Texture的大小。这玩意居然是个4K的纹理,给我吓尿了。尺寸越大,那么修改buffer和数据拷贝的耗时自然也是越大了。所以我修改成了1K的纹理。
因为我手边没有鸿蒙手机。只能翻出了自己珍藏已久的vivo x9开始测试起来,这是一个非常老的手机。性能垃圾的很。正好看看性能优化如何。原始的demo在手机上不涂色的时候,fps45。涂色的时候只有20。 而我优化后的demo。不涂色的时候有60。而涂色的时候有45。这不就妥了嘛。我拍拍手感觉大功告成。拍了个视频给阿杰准备交差了。
顺便说一句,经过我在手机上的测试。涂色Interval我设置为了0,就是说每一个touchMove里都会做涂色点的计算 ,而上传纹理Interval设置为了1/10。这样子涂起来手感比较好。
阿杰拿到代码就兴奋就开始在鸿蒙手机上打包测试了。
“还是不行哎,还是卡的要死了。”
我看着阿杰的鸿蒙手机感到有点意外,因为他的配置比我手上的x9好到不少。怎么会还是卡呢。我只能请阿杰打开调试模型,拍摄一下手机是怎么个卡法。让我看看fps数字的波动。
很快阿杰就发来一段视频。视频里在没有涂色的时候,fps还是稳稳的六十的。而手指一滑动,屏幕直接卡死了。好一会。模型上才出现了涂的颜色。而fps直接降低到0了。
只有涂色的时候卡?我仔细思索了一番,请阿杰将涂色Interval设置为1/60。看一下还卡不卡。
“我靠,不卡了。”阿杰回答。
“我觉得鸿蒙手机的触摸事件是不是触发的非常密集啊。比如在android上只会一秒60次触发。而在鸿蒙上会每秒触发几百次。这就导致了如果在touchMove里做耗时操作,就会卡的要死哦?”我对阿杰说。
可惜我手边没有鸿蒙手机,不然我真的想要测试一下阿杰的鸿蒙手机的触摸时间触发频率到底是多少。
“不过,现在这个东西和我现在预想的好像不太一样,我再给你加点钱。你能继续在追加新功能嘛?”阿杰接着问。