daviddarx Posted February 5, 2019 Share Posted February 5, 2019 Hi everybody, I am starting with Pixisjs and getting a small performance issue with something that should be really simple to process: when I draw a triangle (moveTo, lineTo) on each mousemove event with one of the points which is the mouse position, it performs well at the beginning, but the more i follow on with mouse move, the worse get the performance. After a minute, the FPS ist really low. I made a pen to illustrate it: https://codepen.io/daviddarx/pen/MLEbvE If I clear the graphic at the beginning of each mouse move event (//graphics.clear();), the performance stays good all the time. But unfortunately, it given't the effect that I will reach anymore :( . Am I missing something? Should I try another approach to draw elements on the stage on high frequency without erasing the stage first? Thank you a lot for your support! David Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 5, 2019 Share Posted February 5, 2019 That's a complex question regarding Graphics internals, and how webGLData is formed based on graphics: https://github.com/pixijs/pixi.js/blob/v4.x/src/core/graphics/webgl/GraphicsRenderer.js#L73 I do not know whether its algorithm failing at your case or you add so much data that any algo will fail. Maybe algorithm does not use multiple buffers and uses only one which gets reuploaded on every new triangle, in that case yeah , its supposed to be slow. I hope you have enough knowledge of chunked algorithms ( like stuff separated into several parts) to determine whether its pixi failing on your own, I just dont want to spend my time remembering that part of algo. In that case you can create multiple Graphics instead, and filll only latest one, while other stay static. Yes, some drawing apps draw only new elements on stage. Some are drawing only changed chunks of bitmap data, and remember them in temporary RenderTextures. Its a very big topic that takes a day to explain. One of those drawing apps: https://github.com/wonderunit/alchemancy , sorry for difficult filter stuff (positioning is weird, yeah), but we dont have better open-source example than this one. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 5, 2019 Share Posted February 5, 2019 Looked at example. Now im sure that its fragment shader problem - imagine HOW MANY PIXELS do you draw each frame, its total area of all those triangles. Quote Link to comment Share on other sites More sharing options...
daviddarx Posted February 6, 2019 Author Share Posted February 6, 2019 Hi @ivan.popelyshev, Thank you for your quick answer! Hum, I unfortunately don't understand a lot of what you're telling :'( . Actually, the only part I understand is: "In that case you can create multiple Graphics instead, and filll only latest one, while other stay static.". Should I try with 2 graphics? One for drawing the new triangle with graphics.clears(), and one in background with the result copied there at the beginning of each frame? Did I understand good? And one last question: if y do the same with native js/canvas, without pixijs, should it perform better? Thank you a lot for your help! David Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 6, 2019 Share Posted February 6, 2019 Its a fillrate problem, you spawn so many triangles that total area exceeds what you can safely draw in one frame. https://en.wikipedia.org/wiki/Fillrate Quote Link to comment Share on other sites More sharing options...
Exca Posted February 6, 2019 Share Posted February 6, 2019 What you could do is draw the triangles into a texture and then display that texture on the stage. That way you wouldn't have a very large graphics object redrawn every time. So something like this: //Pseudo code. Might have some syntax errors. var texture = PIXI.RenderTexture.create( app.screen.width, app.screen.height); var graphics = new PIXI.Graphics(); var sprite = new Sprite(texture); app.stage.addChild(sprite); //Draw other shapes you want here to graphics and then draw that to texture also. graphics.beginFill() ... graphics.endFIll(); app.renderer.render(graphics, texture); function mouseMoveHandler() { graphics.clear(); graphics.beginFill(0x000000); graphics.lineStyle(Math.random()*3, 0xffffff, 1); // draw a shape graphics.moveTo(0,0); graphics.lineTo(250, 0); graphics.lineTo(event.pageX, event.pageY); graphics.lineTo(0, 250); graphics.endFill(); app.renderer.render( graphics, texture, false); } ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 6, 2019 Share Posted February 6, 2019 You forgot "false" as a third param (clear) Exca 1 Quote Link to comment Share on other sites More sharing options...
daviddarx Posted February 6, 2019 Author Share Posted February 6, 2019 Oh thank you very much @Exca, I'll try that soon! Quote Link to comment Share on other sites More sharing options...
botmaster Posted February 6, 2019 Share Posted February 6, 2019 Your problem would be the same with any other technology, Sprite2D, Flash, etc ... Would slow down the exact same way. You cannot just keep on drawing new objects (triangle) constantly, it's too much work for the CPU or the GPU or both. The solution > You need to cache. The basic idea: Draw what's NEW with a graphic but draw what's already DRAWN in a texture, you end up with a texture with everything that has already been drawn (a piece of cake for GPU to render) and a graphic with only the latest stokes (expensive but manageable by GPU). When user draws again render your texture (draw cache) with everything the user has done, empty your graphic and start drawing again with it, etc .... Quote Link to comment Share on other sites More sharing options...
daviddarx Posted February 6, 2019 Author Share Posted February 6, 2019 Hi guys! @Exca Thank you for the solution, it works perfekt!! Alelujah! @ivan.popelyshev Thank you for the small correction ? @botmaster Thank you very much for the explication of the solution. I am a complete newby and thought that the caching happens per default, that if I don't clear the graphic it would stays in cache and the only thing that would then happen is the small drawing on the picture which ist already drawn. No I understand it the the graphic not a bitmap is, but an object with all instances "living" there. It will help me further a lot, thank you! The only problem that I now have is: the aliasing doens't work anymore: https://codepen.io/daviddarx/pen/MLEbvE I searched in the documentation of RenderTexture and Sprite, no antialiasing options there. I tried to replace app.renderer.render(graphics, texture, false) with app.renderer.render(graphics, texture, true), but it doens't work neither. Do you have any idea where the problem could come from? Thank you a lot! David Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 6, 2019 Share Posted February 6, 2019 it wont work on RenderTexture, its just not possible in webgl1. But you can try to switch pixi default "app.render()" that is registered in "app.ticker" that way it doesnt clear old framebuffer, but that wont work good on some devices, and workaround includes BLENDMODE.NONE from pixi-v5.. yeah its not pretty Want pretty things - learn how webgl works and make your changes to pixi. 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.