【转】android Canvas OpenGLES
目前在做一个游戏,原来J2ME上的,移到android倒是不复杂,在Canvas绘图这个系统里,封装Image,封装Graphics这些都很容易,该优化的也优化了,但由于有些地方一屏里绘制了较多图片,性能相当不给力。
android既然提供了OpenGL ES,相比硬件图形处理比Canvas这种东东要给力的多,但这个转换也不是那么容易做,网上也没啥这方面介绍,有人做过这方面工作吗?交流交流吧。
首先Canvas不可能直接转化为OpenGLES(否则Google就这样运行Android UI岂不是很快,何必源码中不用),最多只能将Canvas内容绘制到Bitmap上,然后在GLSurfaceView中利用Android提供的GLUtils.texImage2D函数将其当作纹理贴到手机屏幕上,但这样100%会变得比原来还慢(纹理转换很耗时间:(……)
更何况GLES也不是万灵丹,如果真机硬件性能不成,GLES也未必就比Canvas更快,甚至可能低于Canvas(某些该死的低端Android机GLES其实是软件渲染,调用OpenGLES将比Canvas还慢)。
我个人认为,Canvas虽然性能较GLES方法为低(一个配置到位的SurfaceView,和一个配置到位的GLSurfaceView,其实最多也就差10FPS左右),但贵在兼容性够高,只要是Android系统就肯定能跑,而且无论低端或高端机上的表现都相对稳定。如果仅开发2D游戏,除即时战略类型外,基本上也还算得够用。
对于您的游戏帧率过低问题,小弟以为还是应该从您自己游戏方面找原因,比如是不是可以重用的画面没有缓存成一个Bitmap(即使是OpenGLES开发,遇到某一组图片会在一起反复出现时,通常也会将它们绘制到一起作为单独的Texture,而不是分别渲染到屏幕),是不是可以使用RGB565或ARGB4444的Bitmap却使用了ARGB8888,有没有直接使用旋转或缩放图片功能而不是现成的Bitmap贴图(在Android中无论是使用Matrix的scale、rotate等特效方法,还是Canvas的,全部慢的惊人,所以这些特效绝对要直接贴图(至少要绘制完毕后缓存结果成一个Bitmap,再读时利用缓存而不重新运算),一定不能靠这些现成函数去完成)。
还有通过getHolder获得SurfaceHolder后,您有没有将其设置为setType(SurfaceHolder.SURFACE_TYPE_HARDWARE)尝试硬件加速(看真机,试试也没坏处),有没有设置SurfaceHolder为setFormat(PixelFormat.RGB_565) 以减少Canvas本身的渲染损耗,有没有停止Android内置缓存,设置View为setWillNotCacheDrawing(false);setWillNotDraw(false);(这个也看真机,有些真机开缓存反而更快)要知道以上种种因素都会制约您的Canvas速度。
话说我用Canvas做弹幕都可以跑50FPS以上(320x480屏幕,如果是480x800会降到40FPS以上),注意以上几点,每帧几百次drawBitmap应该不会有大问题,至少也该有20多FPS吧……
__________________
先自己调调试试,实在不成把GLES做成J2ME样式的封装,也是出路(比如glColor4f基本等价setColor,glTranslatef基本等价translate,drawImage时就用glDrawArrays堆图像顶点,也无非是封装那些绘图API的事)……
非常感谢2楼。。。
不到万不得已,自然不会考虑改成GLES的,目前工期还是比较紧。但当前的帧率确实太有问题了,每帧300次左右的绘图,FPS只有8帧左右。。。
绘图重用画面之类的问题应该没有了,之前的引擎这方面应该没啥问题,有些地方确实用了ARGB8888创建图片,数量还不少,因为要画许多透明色,没办法,当然可以做采样,把不必要的改成RGB565或ARGB4444这些16位的,但今天我试了下全部写成RGB565,不画透明色,也没快几帧。。。
封装了J2ME里Craphics的drawRegion来画翻转之类,估计这个得改成加载时直接创出翻转后的Bitmap,但感觉用的地方也不多。。。
还有个问题是现在用的卡马可卷轴,我在考虑直接在内存中开出一块儿整张地图来每帧画背景,不使用卷轴的Tile算法,反正内存大,不知道有没有帮助。。。
另外你说的设置SurfaceHolder还没试过,回头试试看。。。
头疼啊,看到有英文介绍android游戏优化的达人推荐必使用GLES,说在绘制很多图片时性能跟Canvas有本质差别,心里有些忐忑,这样搞的话,不知道时间来不来得及,纠结啊。。。