tsm Posted March 25, 2020 Share Posted March 25, 2020 Hi everyone, I work on a particule engine with thousands of particles and thousands of differents textures. I need to be able to tint particles with a different amount of tint for each particles. So I made a shader to do this and use mesh instead of sprite, but the performances are really bad with thousands of particles. I think the shader I made can't be simpler, does Pixi does something internally with sprites that mesh doesn't have ? Here's a exemple with the shader : https://www.pixiplayground.com/#/edit/DuEeDDzZltSRzeAwrWJiy Particles number and mode (mesh or sprite) can be tweeked to see performance differences. Thanks a lot. ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 Welcome to the forums! You are lucky, because right now in v5 we have exact solution for the problem. Yes, pixi gives you ability to make your geometries and even re-use them (like you did), but still, count of drawcalls can be a problem! If you capture one frame with SpectorJS you'll see a problem ( I didnt do it but probably there are too many drawcalls). So, PixiJS actually exposes its batchrenderer! It fills up one geometry for many objects every frame. Demo is here: https://www.pixiplayground.com/#/edit/CMKvgOt-bvlCG4QHdswIP . We didnt add it to examples yet, but we really should do it because of people like you who need it. The idea is to specify "pluginName" for Sprite, Graphics or mesh material. Sprites are always batchable, but in case of Graphics and Meshes you have to make sure isBatchable gets set to "true" so instead of shader pixi pushes data to batcher in `renderBatched` function. Something like that. In your particular case, Sprites are enough, so you dont have to think about what I said in previous line The downside - you have to to tint and other stuff in attributes instead of uniforms. Tint is already handled in demo, so in your case you need extra attribute field for "ratio". tsm and vasilii 1 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 (edited) The other problem is that for tens of thousands of particles updateTransform() will be slow, yeah, Javascript problem. ParticleContainer can solve that but creating custom shader for it isn't covered by any examples, you are on your own. Also it wont handle thousands of textures. Also, in case you create many Sprite instances per every frame - demo can be slow if devtools are open in chrome. Yes, it can happen, do not be surprised if it happens for you. Edited March 25, 2020 by ivan.popelyshev vasilii 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 I just thought.. if you'll have thousands of textures (not texture regions, but baseTextures), thousands of "renderer.texture.bind" will also slow you down. I dont know what to do in that case, except that you can use atlases. vasilii 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 (edited) Oh I forgot, here's how I pack extra data in arguments: https://github.com/gameofbombs/pixi-heaven/blob/master/src/twotint/sprites/HeavenBatchRenderer.ts . Its not covered in that playground demo. Original pixijs batch geom: https://github.com/pixijs/pixi.js/blob/dev/packages/core/src/batch/BatchGeometry.ts#L39 , original interleave: https://github.com/pixijs/pixi.js/blob/dev/packages/core/src/batch/AbstractBatchRenderer.ts#L729 There are also other things that can be overriden - like binding uniforms for groups of sprites or handling 2 textures per sprite instead of one - that all is possible because our BatchRenderer became quite modular a few months ago. Edited March 25, 2020 by ivan.popelyshev vasilii 1 Quote Link to comment Share on other sites More sharing options...
tsm Posted March 25, 2020 Author Share Posted March 25, 2020 Hi Ivan, thanks a lot for your quick answers. I'll check your batchrenderer exemple it looks very interesting for my problem. ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 (edited) > it looks very interesting for my problem. Basically its configuration of pixijs default sprite renderer. What was only possible through full CTRL+C before, now can be done in overrides. Colors, global animations - that's easiest case. I use it for 2.5d/3d emulation: https://github.com/pixijs/pixi-projection , for double- tinting (pixi-heaven) and for fast masks (thousands of sprites - OK) , again, in pixi-heaven repo. In PixiJS v4 i had to make my own SpriteRenderer that could be partially overriden - and it was hard to recommend it for other people hax. Edited March 25, 2020 by ivan.popelyshev tsm 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 (edited) Oh, look: https://github.com/pixijs/pixi-batch-renderer , @Shukant Pal made custom configurator for it. Maybe it can be useful for you! Edited March 25, 2020 by ivan.popelyshev tsm 1 Quote Link to comment Share on other sites More sharing options...
tsm Posted March 25, 2020 Author Share Posted March 25, 2020 Hi Ivan, I tried to use the BatchPluginFactory, I managed to provide my vertex & fragment shaders, geometry, and vertexSize, but do you know how can I override the inteleave ? Here is my code : https://www.pixiplayground.com/#/edit/MhxqhNXcDOlx6uq0x6ezx Thanks Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 25, 2020 Share Posted March 25, 2020 (edited) 11 hours ago, ivan.popelyshev said: Oh I forgot, here's how I pack extra data in arguments: https://github.com/gameofbombs/pixi-heaven/blob/master/src/twotint/sprites/HeavenBatchRenderer.ts . Its not covered in that playground demo. Original pixijs batch geom: https://github.com/pixijs/pixi.js/blob/dev/packages/core/src/batch/BatchGeometry.ts#L39 , original interleave: https://github.com/pixijs/pixi.js/blob/dev/packages/core/src/batch/AbstractBatchRenderer.ts#L729 You need your own plugin factory. Look closer in my HeavenBatchRenderer. Yes, its an extra step that usually belongs to dependency injection frameworks - specifying factory instead of creating renderer itself. Cant edit your demo right now, its not a minor change and I already have queue of them. Edited March 25, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
tsm Posted March 26, 2020 Author Share Posted March 26, 2020 No problem Ivan, I'll do it. Thanks again. ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
tsm Posted March 27, 2020 Author Share Posted March 27, 2020 Hi Ivan, I managed to make my plugin factory. It's great, I can display my special sprites with less drawcalls & the framerate of classic sprite. Thanks a lot for your time ! https://www.pixiplayground.com/#/edit/QEGbh9v-WSwHTWX6-I1ew ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 (edited) I looked in profiler - Idle 50% but FPS is only 30 for me - its probably GPU-bound.. I ran SpectorJS - yes, you have too many bindTextures- 100 textures is too big amount, we have only 16 or 32 locations usually - that means on random textures you'll get all 20k bindTexture operations You need a runtime atlas - can only give tips about that because i did not move pixi-super-atlas to v5 yet. Edited March 27, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 Here it is, serial bindTexture. What batcher does in this case - it reduces numbe of drawcalls, but texture binds are more important and the only way for them to go down is to use super-atlas.. Or you can try sort your sprites by texture so thre will be huge chunks of sprites with same set of textures consequtively https://monosnap.com/file/CuWwAtRVtKQtjGZuCfOME6IIqHqF4f Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 OK, here's basically what you have to do: 1. Prepare a sprite for every textures of your favorite size. 2. make grid of those sprites. 3. render them on RenderTexture (calculate size needed) 4. make partial textures out of it. "new PIXI.Texture(renderTexture.baseTexture, new PIXI.Rectangle(x,y,w,h));" 5. Use those 100 textures for your giant amount of sprites. tsm 1 Quote Link to comment Share on other sites More sharing options...
tsm Posted March 27, 2020 Author Share Posted March 27, 2020 (edited) Thanks for the advice Ivan. The app I'm developping needs to display thousands of sprites with thousands of differents textures, atlases are interesting but I think I gonna have some problems with depth sorting. Every sprite can change his depth at any moment. Atlases is the next performance feature I need to test but it's not gonna be now. The batcher I implemented thanks to you makes a great difference, it is sufficient for now. Edited March 27, 2020 by tsm mistake Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 28, 2020 Share Posted March 28, 2020 arrays.sort() should work just fine even on 10k elements. Pixi has it in contaner, just enable sorting and sort() will be called in frames if you changed any of elements zIndex - es Quote Link to comment Share on other sites More sharing options...
tsm Posted April 8, 2020 Author Share Posted April 8, 2020 Hi Ivan, hope you are doing well. I'm struggling with the shader in the batcher you help me build : https://www.pixiplayground.com/#/edit/U3Sk72dkfAG0ZjriNxE4r My alpha channel isn't working correcltly, even with 0.0 instead of color.a line 14, I can't get the correct transpancy. Even with vec4(1.0, 0.0, 0.0, 0.0) I have red with no transparancy at all. Do you see where's my error ? Thanks. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 8, 2020 Share Posted April 8, 2020 I dont understtand what exactly do you want with alpha channel, but I can deduce by your shader code: Yes, you assume that `color.rgb` is not premultiplied. In fact, its RGB channels already multiplied by alpha. So , either you divide by alpha, then ultiplying whole result by alpha, or you just add " * color.a" for vColor: https://www.pixiplayground.com/#/edit/kv--XY25TNraHlDlA_Q3r Here is example of how to deal with premultiplied alpha: https://github.com/pixijs/pixi-picture/blob/master/src/OverlayShader.ts#L18 1. if 0 , return 0 2. if not 0, divide by alpha, do your things 3. dont forget to multiply by alpha in the end. If that is not enough, please explain my what are you trying to do and how should it look, becausse right now both mine and your examples look same Quote Link to comment Share on other sites More sharing options...
tsm Posted April 8, 2020 Author Share Posted April 8, 2020 Sorry Ivan, I was doing some tests on pixiplayground and wrong code has been saved. This is the code I was talking about : https://www.pixiplayground.com/#/edit/kEz5EE6EnJtA-gWPw1O8B I don't understand why the alpha parameter (color.a) has no impact. Even if I set it to 0.0, I still see some pixels. Quote Link to comment Share on other sites More sharing options...
tsm Posted April 8, 2020 Author Share Posted April 8, 2020 Ok never mind, multiplying my tint color with texture color.alpha is working like you did on your exemple. The code : https://www.pixiplayground.com/#/edit/v1ul6FO1tA5b9R4pQTf30 I still don't understand why gl_FragColor = vec4( textureColor.rgb, 0.0) is showing some pixels, but I'm not experimented with shader. Thanks a lot Ivan ! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 8, 2020 Share Posted April 8, 2020 (edited) Its premultiplied alpha. We store not R,G,B but Ra,Ga,Ba. Blendmode has coefficients (1, 1-src_alpha), not (src_alpha, 1-src_alpha). So, (R,G,B,0) is actually additive color, it just adds a value to each channel. If we dont store it like that, we'll get huge problems with linear filtering. http://www.adriancourreges.com/blog/2017/05/09/beware-of-transparent-pixels/ Welcome to 2d graphics To fix the thing either premultiply vColor.rgb to color.a , either divide by alpha and multiply by it in the end. Edited April 8, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 8, 2020 Share Posted April 8, 2020 (edited) This is specific to 2d graphics, and yes, it blew up brains of many people who studied it. I love those kind of issues when people are beating themselves on glass doors that I too didn't notice before I feel happy each time someone else gets it too. Edited April 8, 2020 by ivan.popelyshev tsm 1 Quote Link to comment Share on other sites More sharing options...
tsm Posted April 9, 2020 Author Share Posted April 9, 2020 Thanks for the link, I will study that, I wasn't aware of premultiplied alpha, it's interesting (it is blewing my brain already ?). ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 9, 2020 Share Posted April 9, 2020 (edited) Wanna see more things that can trigger the same feeling? https://github.com/pixijs/pixi.js/issues/6507 Edited April 9, 2020 by ivan.popelyshev tsm 1 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.