Test Match : click on images to watch
V.S
My results with HTML5 canvas :
Chrome 7.0.517.44 : CPU ~30%
Firefox 3.6.10 : CPU ~50%
IE 8.0.6001 : not working…
My results with Flash Player 10.1
Chrome 7.0.517.44 : CPU ~7% and stable memory usage.
Firefox 3.6.10 : CPU ~7% and stable memory usage.
IE 8.0.6001 : CPU ~1% and stable memory usage.
HTML Source
<!DOCTYPE html> <html> <head> <title>SpherePixels3D</title> <style> body { background-color:#000000; } #canvasHTML { border: 1px dotted #808080; } </style> </head> <body> <canvas id="canvasHTML" width="600" height="600"></canvas> <script type="text/javascript" src="SpherePixels3D.js"></script> </body> </html>
Javascript Source (SpherePixels3D.js)
// pre-calc values var N_POINT1=60; var N_POINT2=60; var N_POINT3=3600; var RADIUS = 150; var RADIAN = Math.PI / 180; var FOCUS = 280; var CENTER_X; var CENTER_Y; // vars var width; var height; var context; var points; var bitmapdata; var bitmapdataArray; var theta; var i, j, p, xx, yy, zz, scale; window.onload = function() { var canvas = document.getElementById('canvasHTML'); if (! canvas || ! canvas.getContext ) {return false;} else { width = canvas.width; height = canvas.height; CENTER_X = width >> 1; CENTER_Y = height >> 1; theta = 0; points = []; context = canvas.getContext('2d'); // init, creating all the points of the pseudo-sphere var theta1, theta2; for(i=0; i < N_POINT1; i++) { theta1 =(360 / N_POINT1) * i * RADIAN; for(j=0; j < N_POINT2; j++) { theta2=((180 / N_POINT2) * j - 90) * RADIAN; xx=RADIUS * Math.cos(theta2) * Math.sin(theta1); yy=RADIUS * Math.sin(theta2); zz=RADIUS * Math.cos(theta2) * Math.cos(theta1); points[i * N_POINT2 + j]=new Point3D(xx, yy, zz, 255,255,255); } } // my update loop witch is equivalent to 40FPS (1000/25); setInterval("onEnterFrame()", 25); } }; // update loop function onEnterFrame() { // clear the canvas with the bgclor context.fillStyle = "#000000"; context.fillRect(0,0,width, height); bitmapdata = context.getImageData(0, 0, width, height); bitmapdataArray = bitmapdata.data; // the new x/y positions for(i=0 ; i < N_POINT3; i++) { p=points[i]; // a simple rotation aroud the Y axis xx =p.x * Math.cos(theta * RADIAN) + p.z * Math.sin(theta * RADIAN); yy = p.y; zz = p.z * Math.cos(theta * RADIAN) - p.x * Math.sin(theta * RADIAN); scale = FOCUS * 1.5 / (FOCUS - zz); xx = ((xx * scale)|0) + CENTER_X; yy = ((yy * scale)|0) * (-1) + CENTER_Y; j = (yy * width + xx)*4; bitmapdataArray[j] = p.rr; bitmapdataArray[j + 1] = p.gg; bitmapdataArray[j + 2] = p.bb; bitmapdataArray[j + 3] = p.aa; // RBVA mode instead of ARVB... } context.putImageData(bitmapdata,0,0); theta ++; } // "class" point3D function Point3D(x, y, z, rr, gg, bb) { this.x = x; this.y = y; this.z = z; this.rr = rr; this.gg = gg; this.bb = bb; this.aa = 255; }
AS3 source (Main.as)
package { import flash.events.ContextMenuEvent; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.ui.ContextMenu; import flash.ui.ContextMenuItem; import flash.ui.ContextMenuBuiltInItems; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; /** * ... * @author YopSolo * In this demo i do NOT use the native3D of the flash player * */ [SWF(width = "600", height = "600", backgroundColor = "#000000", frameRate = "40")] public class Main extends Sprite { // pre-calc values private const N_POINT1:int = 60; private const N_POINT2:int = 60; private const N_POINT3:int = 3600; private const RADIUS:int = 150; private const RADIAN:Number = Math.PI / 180; private const FOCUS:int = 280; private var CENTER_X:int; private var CENTER_Y:int; // useless //private var width; //private var height; //private var context; //private var points; //private var bitmapdataArray; private var points:Vector.<Point3D> = new Vector.<Point3D>; // vector are just typed Array, here it's an Array of custom object Point3D private var bitmapdata:BitmapData; private var canvas:Bitmap; private var theta:int = 0; private var i:int, j:int, p:Point3D, xx:Number, yy:Number, zz:Number, scale:Number; public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); // right click menu const VERSION:String = "0.00"; var newContextMenu:ContextMenu = new ContextMenu; newContextMenu.hideBuiltInItems(); var cmi:ContextMenuItem = new ContextMenuItem("FLASH/HTML5 benchmark 11/2010" + VERSION); newContextMenu.customItems.push(cmi); cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickMenuItem ); this.contextMenu = newContextMenu; } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.stageFocusRect= false; CENTER_X = stage.stageWidth >> 1; // 300 CENTER_Y = stage.stageHeight >> 1; // 300 // init, creating all the points of the pseudo-sphere var theta1:Number, theta2:Number; for(i=0; i < N_POINT1; i++) { theta1 = (360 / N_POINT1) * i * RADIAN; for(j=0; j < N_POINT2; j++) { theta2 = ((180 / N_POINT2) * j - 90) * RADIAN; xx = RADIUS * Math.cos(theta2) * Math.sin(theta1); yy = RADIUS * Math.sin(theta2); zz = RADIUS * Math.cos(theta2) * Math.cos(theta1); points[i * N_POINT2 + j] = new Point3D(xx, yy, zz, 0xFFFFFFFF); } } // creation of the Action Script 3 'Canvas' bitmapdata = new BitmapData( 600, 600, true, 0x0 ); // the datas canvas = new Bitmap( bitmapdata ); // the visual object // my update loop, 40FPS look at line 15 this.addEventListener( Event.ENTER_FRAME, _onEnterFrame ); addChild( canvas ); } // update loop private function _onEnterFrame(e:Event):void { // clear the canvas with the bgclor bitmapdata.fillRect( bitmapdata.rect, 0x0 ); // the new x/y positions for (i = 0 ; i < N_POINT3; i++) { p = points[i]; // a simple rotation aroud the Y axis xx = p.x * Math.cos(theta * RADIAN) + p.z * Math.sin(theta * RADIAN); yy = p.y; zz = p.z * Math.cos(theta * RADIAN) - p.x * Math.sin(theta * RADIAN); scale = FOCUS * 1.5 / (FOCUS - zz); xx = (xx * scale ) + CENTER_X; yy = ( yy * scale ) * ( -1) + CENTER_Y; bitmapdata.setPixel32( xx, yy, p.color ); } theta ++; } // -- Right click menu action private function _onClickMenuItem(e:ContextMenuEvent):void { navigateToURL( new URLRequest( "http://www.yopsolo.fr/wp/"), "_blank" ); } } } [/as3] <strong>AS3 source (Point3D.as)</strong> [as3] package { /** * ... * @author YopSolo */ public class Point3D { public var x:int; public var y:int; public var z:int; private var _color:uint; public function Point3D(x:int = 0, y:int = 0, z:int = 0, color:uint = 0xFFFFFFFF) { this.x = x; this.y = y; this.z = z; this._color = color; } // a read only property public function get color():uint { return _color; } } }
On HTC Desire whith froyo (android 2.2) the HTML5 version is slow and same thing on ipHone 3gs/4g.
HTML5 – QRCode
FlashVersion – QRCode
My conclusion is : HTML5 consume more CPU than Flash, HTML5 monomaniacs are lying ;)
But my real conclusion is that if i had to write something with a high refresh rate ( a game blitting engine for example ) it’s a better choice to do it with Flash.