HernanZh Posted June 11, 2016 Share Posted June 11, 2016 Hello everyone, I'm working on a little project that I named Pixi-Canvas. The idea is to wrap the Pixi renderer in an API that's similar to the 2d canvas API. This allows you to use functions such as context.drawImage, context.fillRect, context.save, context.rotate etc. like you would with canvas.getContext("2d")! If you're already using Pixi or Phaser, then obviously this is not useful to you. The project is very similar to webgl-2d (if anyone remembers that), except this uses Pixi as the underlying renderer. You can find this and more info here https://github.com/LuckyKat/pixi-canvas. Please check it out! Motivation While Pixi is the best and fastest renderer out there, I found that Pixi introduces a lot of structures that forces you to work in a certain way. I feel like it's half a game engine already! For my own game engine, I wanted to introduce my own entity-component system, parent-child relations and get in between the render calls per sprite. I felt that Pixi makes that pretty difficult! Working with the 2d canvas API in that sense is much easier, so I wrote a wrapper that could draw pixi sprites like you call context.drawImage. I decided to share this method and write a library that's easy to use. Performance / difference with Pixi Using Pixi-Canvas will definitely be slower than using Pixi normally. To test and compare the performance, I replicated the Pixi bunnymark. On my Surface Pro 4 i5, the amount of bunnies I could spawn before hitting 30 fps: Canvas 2d: ~4000 bunnies Pixi-Canvas: ~30.000 bunnies Pixi: ~55.000 bunnies Note that this seems to differ a lot per device! I tried this on a Mac Mini the other day and Pixi-Canvas performance was a mere 5000 bunnies. So please give this a try on your own computer and let me know what your performance is. For comparison's sake, I copied Pixi's original bunnymark and turned off the ParticleContainer. ParticleContainers are much faster, but very limited in functionality, so it would be an unfair comparison. I uploaded the bunnymarks here (If anyone from goodboydigital is not ok with this, let me know and I'll take it down): Pixi-Canvas: http://www.heigames.com/html5/bunnymark Pixi original without particlecontainers: http://www.heigames.com/html5/pixibunnymark I've tried to make Pixi-Canvas as optimal as possible of course. Under the hood, it does not use Pixi as you would normally. I'd love to know any tips that could make Pixi-Canvas faster! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 11, 2016 Share Posted June 11, 2016 PIXI can be separated to multiple layers: 1. Scene graph: DisplayObject/Container/Sprite 2. Renderer plugins: Sprite Renderer, Graphics Renderer 3. Renderer itself: WebGLRenderer, CanvasRenderer 4. Texture storage: Texture/BaseTexture 5. Loaders 6. Low-level webgle for pixiv4: pixi-gl-core I understand why do you want to get rid of (1) and wrap calls of (2) , but you are also wrapping (3), which is very bad. You just have to create your own renderers instead of (2) that accept the same parameters as context2d. BaseTexture optimization is basic thing, and within your approach its impossible to use spritesheets. Quote Link to comment Share on other sites More sharing options...
HernanZh Posted June 11, 2016 Author Share Posted June 11, 2016 Um, spritesheets work fine...?? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 11, 2016 Share Posted June 11, 2016 20 minutes ago, HernanZh said: Um, spritesheets work fine...?? Can your drawImage accept Texture as a param, or do you have to pass all coords of a certain frame to it? The whole point of abstraction is that you dont have to care about whether you are using a spritesheet or not. Quote Link to comment Share on other sites More sharing options...
HernanZh Posted June 12, 2016 Author Share Posted June 12, 2016 I think you're misunderstanding, I'm replicating the context 2d API. So in this case: https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage drawImage take a HTML Image as first parameter and then you pass other coordinates to this. Abstraction is a job for whatever game engine you use, not the renderer! Quote Link to comment Share on other sites More sharing options...
themoonrat Posted June 12, 2016 Share Posted June 12, 2016 Slotted it into one of my games that uses 2 canvases layered on top of each other.... and..... everything pretty much worked!!! Which was a massive pleasure, since last time i tried that old webgl-2d project, it drew my game into a small corner of the window! Will investigate more for to see if there are actual performance benefits for the variety of devices I have to develop for. The only place it didn't work correctly is when dealing with globalAlpha I believe. The sprite class I use does a ctx.save(), changes globalAlpha, draws the image, then does a ctx.restore(). With pixi-canvas, as more and more faded images are drawn the globalAlpha decreases further and further towards 0, until the game is fully transparent! Quote Link to comment Share on other sites More sharing options...
HernanZh Posted June 12, 2016 Author Share Posted June 12, 2016 Oh, I was under the impression globalAlpha was ignored by save and restore. I added that, should work now I think. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 12, 2016 Share Posted June 12, 2016 1 hour ago, HernanZh said: I think you're misunderstanding, I'm replicating the context 2d API. So in this case: https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage drawImage take a HTML Image as first parameter and then you pass other coordinates to this. Abstraction is a job for whatever game engine you use, not the renderer! Replicating is pointless, unless you add some extra features to it. I think I'll make my own canvas2d API imitation that can be used at the same time as PIXI scene graph. Quote Link to comment Share on other sites More sharing options...
HernanZh Posted June 12, 2016 Author Share Posted June 12, 2016 Cool, I'd love to see! Quote Link to comment Share on other sites More sharing options...
caymanbruce Posted January 17, 2017 Share Posted January 17, 2017 I can't see the demos. I can only see blank pages. What's wrong with your site? I thought your demos are canvas-based? Quote Link to comment Share on other sites More sharing options...
xerver Posted January 18, 2017 Share Posted January 18, 2017 This is a cool way to allow applications using the canvas-2d API to start using pixi immediately. Which for WebGL users would offer speed boosts, without them having to change any code. Very cool @HernanZh, thanks for the share. Quote Link to comment Share on other sites More sharing options...
HernanZh Posted February 9, 2017 Author Share Posted February 9, 2017 Thanks! Should probably try to add pixi v4 support at some point... Quote Link to comment Share on other sites More sharing options...
Codestar Posted February 9, 2017 Share Posted February 9, 2017 This might breathe some life into older gamedev libraries like ImpactJS, great work! Quote Link to comment Share on other sites More sharing options...
Kalith Posted February 9, 2017 Share Posted February 9, 2017 I did something not so different a while back, you might want to take a lok at: https://github.com/karellodewijk/canvas-webgl. It's an implementation of the canvas2D API in webgl. I got pretty good compatibility with the canvas2D api, I certainly got a lot closer than webgl-2D ever did. I'd say it will mostly work as a canvas2D replacement. I did run into issues while trying to get any kind of performance out of it. Basically I ran into two issues. For webgl to be fast you need to batch as many operations as you can into a single draw call. I was sort of trying in the end to delay actually drawing anything until the next animation frame, but it's not so easy. Canvas applications often change the transform or clipping planes, etc, so you have a choice of dealing with all of that in the shader, which gets complex really quickly or sending a draw call every time it happens, which tanks performance. I didn't end up committing my progress here as it broke a lot of the compatibility. Another issue I ran into is that I ended with some pretty cpu intensive algorithms, especially the polyline algorith/line tesselation, which I wrote. And the triangulation algorithm, which I borrowed. Maybe with webgl2, when geometry shaders are a thing you can offload that to the gpu, but writing it in javascript is never going to be great imo. Anyway it was interesting to work on. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.