Jump to content

Shader performances


tsm
 Share

Recommended Posts

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.
 

Link to comment
Share on other sites

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".

Link to comment
Share on other sites

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 by ivan.popelyshev
Link to comment
Share on other sites

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 by ivan.popelyshev
Link to comment
Share on other sites

 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 by ivan.popelyshev
Link to comment
Share on other sites

11 hours ago, ivan.popelyshev said:

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 by ivan.popelyshev
Link to comment
Share on other sites

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 by ivan.popelyshev
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by tsm
mistake
Link to comment
Share on other sites

  • 2 weeks later...

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.

 

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by ivan.popelyshev
Link to comment
Share on other sites

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 by ivan.popelyshev
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...