Jump to content

setting material on sps causes webGL error


Baker Xiao
 Share

Recommended Posts

Hi,

It seems setting a material with diffuse texture on a solid particle system-generated mesh would cause webGL errors. We have a PG repro in:

https://www.babylonjs-playground.com/#ZFH51N#1

The errors reported in the console are: [.Offscreen-For-WebGL-0x7f8318dd3a00]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2

Rendering the SPS without the material works perfectly fine. Any clue what could be causing the problem?

Link to comment
Share on other sites

11 hours ago, jerome said:

Did you check that the imported mesh model has UVs ?

The SPS copies the mesh model settings (geometry, uvs, colors, etc) when building its own geometry. If something lacks in the model, then it lacks in the SPS...

That might be it! Although we did try setting the uvs value of the SolidParticles. Is that not supposed to help with this case?

Link to comment
Share on other sites

btw @jerome we are running into another problem: https://www.babylonjs-playground.com/#N6PH8X

as mentioned in the documentation, we are expecting computeParticleRotation=false to prevent updates, but still allow a rotation to be set initially. However setting it to false seems to make all following setParticle calls to reset the rotation to 0. Any idea what we might be missing?

Link to comment
Share on other sites

This is the expected behavior actually.

The SPS is designed to be able to manage a big number of solid particles, but everything is done CPU side. Including the rotation computations, what are the one the heaviest part of all the internal computations .

So choices were done to give priority to some optimizations over some others :

- only the particle initial status is stored (the status at build time) as a reference (imagine it's some mesh local space, in comparison)

- only the translation and the scaling, among all the possible transformations, are applied anyway from this initial status when calling setParticles()... meaning that, if the rotation computation is disabled, the initial rotation (at build time) only is kept (it's zero, by default). This is the case you're encountering and this is done in purpose for users wanting faster animation without rotations.

That said, if you need to give only one initial rotation to your particles, then pass some positionFunction as a parameter to addShape() before building the SPS. This position function will modify the initial geometry (so the initial status) of the particles added by this call. Thus, you could set them with your custom initial rotation. Any further call to setParticles(), even with computeRotation set to false, won't reset this initial status to zero.

http://doc.babylonjs.com/overviews/solid_particle_system#create-an-immutable-sps

As a comparison, the positionFunction would be a way to bake your own transformation in the mesh local space at construction time.

 

In the contrary, if you need to update the particle rotations at least once after the SPS construction and if you need to re-apply this rotation on next calls of setParticles(), you musn't unfortunately set computeRotation to false then.

Link to comment
Share on other sites

5 minutes ago, jerome said:

This is the expected behavior actually.

The SPS is designed to be able to manage a big number of solid particles, but everything is done CPU side. Including the rotation computations, what are the one the heaviest part of all the internal computations .

So choices were done to give priority to some optimizations over some others :

- only the particle initial status is stored (the status at build time) as a reference (imagine it's some mesh local space, in comparison)

- only the translation and the scaling, among all the possible transformations, are applied anyway from this initial status when calling setParticles()... meaning that, if the rotation computation is disabled, the initial rotation (at build time) only is kept (it's zero, by default). This is the case you're encountering and this is done in purpose for users wanting faster animation without rotations.

That said, if you need to give only one initial rotation to your particles, then pass some positionFunction as a parameter to addShape() before building the SPS. This position function will modify the initial geometry (so the initial status) of the particles added by this call. Thus, you could set them with your custom initial rotation. Any further call to setParticles(), even with computeRotation set to false, won't reset this initial status to zero.

http://doc.babylonjs.com/overviews/solid_particle_system#create-an-immutable-sps

As a comparison, the positionFunction would be a way to bake your own transformation in the mesh local space at construction time.

 

In the contrary, if you need to update the particle rotations at least once after the SPS construction and if you need to re-apply this rotation on next calls of setParticles(), you musn't unfortunately set computeRotation to false then.

Ah I see. I think the positionFunction is a good solution to this problem. Will try it out! Thanks again!

Link to comment
Share on other sites

https://www.babylonjs-playground.com/#N6PH8X#1

mmhh... the positionFunction doesn't seem to bake the initial status either. As everything was done by choices, I have to remember the reason why by checking the code back.

All the rest I said in the former post is right anyway, about how the rotations are computed or not from the initial status.

Link to comment
Share on other sites

1 minute ago, jerome said:

https://www.babylonjs-playground.com/#N6PH8X#1

mmhh... the positionFunction doesn't seem to bake the initial status either. As everything was done by choices, I have to remember the reason why by checking the code back.

All the rest I said in the former post is right anyway, about how the rotations are computed or not from the initial status.

Hmm... in that case, what's a good way to address the scenario where we need to rotate some of the particles initially but never rotate them again? Right now what I'm doing is to never call setParticles again, but that prevents us from changing the position of the particles as well. Seems it would be a good addition to allow some initial transformations to be baked into the geometry. 

Link to comment
Share on other sites

Ok, I got it about the reason.

Actually, the transformations (translation, scaling, rotation but also billboard) are required to be done in certain order like for meshes : rotations come always before translations.

That's why, storing in memory only the global last computed coordinates to pass to the GPU for performance reasons, we need to re-apply the rotation computation each time to get new final coordinates as the SPS doesn't store each particle vertex last state coordinates, but only the transformation (position, rotation, scaling) to apply to all of them.

Not sure I'm clear...

Ex : 1 SPS is 10K particles and is a big geometry : millions of coordinates to pass to the GPU (so one big final array)

each particle stores its own set of transformations and a reference to its shared geometry model

each particle is, say, 40 or 50 vertices, so hundreds of coordinates per particle stored successively in the final array

each particle transformation computation updates in the big final array the part (so hundreds of floats) related to this current particle from its set of transformations

 

As particles share the same geometry model and as the particle vertex last state coordinates isn't stored, there's no per particle baking possibility for now unless implementing some system that would multiply the memory consumption by far.

Nevertheless, I will try to do a way to this ...

 

In your case, as you have to call setParticles() to reapply the rotations, the right way is to call it only when necessary (not every frame maybe), maybe also to use the start and end indexes ( http://doc.babylonjs.com/overviews/solid_particle_system#start-and-end-indexes-for-setparticles ) to modify only the required particles.... and to tolerate the rotation computation when unavoidable ;-)

 

 

Link to comment
Share on other sites

10 minutes ago, jerome said:

Ok, I got it about the reason.

Actually, the transformations (translation, scaling, rotation but also billboard) are required to be done in certain order like for meshes : rotations come always before translations.

That's why, storing in memory only the last computed coordinates to passed to the GPU for performance reasons, we need to re-apply the rotation computation each time to get new final coordinates as the SPS doesn't store each particle vertex last state coordinates, but only the transformation (position, rotation, scaling) to apply to all of them.

Not sure I'm clear...

Ex : 1 SPS is 10K particles and is a big geometry : millions of coordinates to pass to the GPU (so one big final array)

each particle stores its own set of transformations and a reference to its shared geometry model

each particle is, say, 40 or 50 vertices, so hundreds of coordinates stored successively in the final array

each particle transformation computation updates in the big final array the part (so hundreds of floats) related to this current particle from its set of transformations

 

As particles share the same geometry model and as the particle vertex last state coordinates isn't store, there's no per particle baking possibility for now unless implementing some system that would multiply the memory consumption by far.

Nevertheless, I will try to do a way to this ...

 

 

Ahhh, I got the picture. Looks like there's a tradeoff between memory v.s. compute.. 

Link to comment
Share on other sites

3 minutes ago, jerome said:

Exactly

And as we deal with thousands or dozens of thousands occurences, we need to make choices : multiply CPU cycles or (far) more memory allocation

If there's no solution that satisfies both, one idea is to make it a setting so that the user can choose to optimize towards CPU or memory? For us, the situation is kind of awkward because we just have about 50 particles... using instanced meshes has its own overhead, so I'm using SPS. I would definitely want to give up some memory to save CPU cycles given the low amount of particles. But I totally see that enabling these choices is a lot of work. :P 

Link to comment
Share on other sites

If you have only 50 particles, you can keep the rotation computations enabled anyway, you won't even notice the difference compared to disabled rotations. That's just a speck of dust for the CPU.

I thought you had something like 10K particles. At this level the optimizers really matter. But for 50 particles, the difference between computer/un-computed rotations would be only micro-seconds... nothing to be concerned about :)

So my advice would be : keep the rotation computations enabled and enjoy all the SPS other features ! 

 

 

Note : for any standard mesh, its WorldMatrix (so all its transformations : position, scaling, rotation) is computed/cached anyway, even if it's not rotated, translated from a draw call to the other. As it's quite complex to guess what a user wants to do or has just done with all its objects in the scene, plenty of computations are done under the hood to be sure that's things are in the final right place, even when un-changed.

Link to comment
Share on other sites

  • 4 months later...

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