Baker Xiao Posted September 22, 2017 Share Posted September 22, 2017 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? Quote Link to comment Share on other sites More sharing options...
jerome Posted September 22, 2017 Share Posted September 22, 2017 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... Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 22, 2017 Author Share Posted September 22, 2017 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? Quote Link to comment Share on other sites More sharing options...
jerome Posted September 22, 2017 Share Posted September 22, 2017 Setting the UVs in the SPS just modifies the mesh UV initial values by shifting them for some percentage but it can invent these initial values. Your model needs UVs if you want to apply a texture anyway. Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 22, 2017 Author Share Posted September 22, 2017 1 minute ago, jerome said: Setting the UVs in the SPS just modifies the mesh UV initial values by shifting them for some percentage but it can invent these initial values. Your model needs UVs if you want to apply a texture anyway. Got it. Thanks a lot @jerome! Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 22, 2017 Author Share Posted September 22, 2017 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? Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 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. Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 Ooops maybe I spoke too fast I need to check if it really bakes the transformation or not, just can't remember. Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 23, 2017 Author Share Posted September 23, 2017 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! Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 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. Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 23, 2017 Author Share Posted September 23, 2017 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. Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 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 ;-) Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 23, 2017 Author Share Posted September 23, 2017 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.. Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 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 Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted September 23, 2017 Author Share Posted September 23, 2017 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. Quote Link to comment Share on other sites More sharing options...
jerome Posted September 23, 2017 Share Posted September 23, 2017 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. Baker Xiao 1 Quote Link to comment Share on other sites More sharing options...
jerome Posted January 25, 2018 Share Posted January 25, 2018 old thread up ... An internal modification in the SPS now stores each solid particle (sort of) rotation matrix. This means the particle last rotation status is kept even when setting the SPS property .computeParticleRotation to false now GameMonetize 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.