Particle physics on GPU

I am new to the forums and this is my first time posting so bear with me. So I am trying to create a particle simulation where each particle bounces off each other particle. I was able to get everything up and running using fragment shader and having a particle object use it to look up vertex positions, however the problem I have is that every particle is checking every other particle.

I was hoping to be able to create a grid system so that particles only have to compare to neighbor particles however I am not sure if this is even possible. I am using floating point texture and after so e research it looks like you can’t read from them, and I feel like the only way to get this to work is create the grid lookup table off the gpu. I was hoping someone with more experience could give me some guidance or advice for getting try simulation to run faster (currently can only do 1k particles and it still starts to lag with the loop over every particle implementation )

Where did you read this? You can read. You probably should provide a fiddle.

Thanks a ton for the response! I will find where I read that, but when I tested it using the renderer.readpixels (or something similar to that), it said you can only read unsigned bytes. I am talking about reading the texture with JavaScript. I will make a fiddle when I am able to get on my computer later tonight. I really appreciate the response

Oh, i got this as using a float texture as uniform. I can’t tell about copying the data into a buffer, but i never heard there are limitations. But if there really is a limitation in this case i don’t think it’s still in WebGL 2, need to take a look.

Edit: Anyway, it would help if you describe your current implementation and how you want to solve collisions. I thought you simulate the particle flow in a texture with a separate ping-pong texture and use the previous state for collision detection on the GPU.

Yeah, there very possibly might be a way to do it, and what I was reading is out dated.

Unfortunately I can’t post a working example of what I have, however it might be easier for me to just put it to a web server with a link to a public github page because there are multiple files but it is still a very small project.

But basically what I’m doing now is I keep track of the positions and the previous positions. I update the positions and then handle collisions then constrain the particles. I basically have three render functions, however I do call the collision one multiple times to keep the particles from overlapping (one iteration isn’t enough for when they start piling up). And I derive the velocity from the position and old position. I will post an example later though.

This three.js example might help as an orientation guide. It’s a basic GPU particle system.

https://threejs.org/examples/#webgl_gpu_particle_system

Thanks for the link. So I looked at the source and I don’t see any reference to the shader code. Also it doesn’t look like it has any inter particle interaction. Maybe I am missing that though. The inter particle interaction is the real challenge I am having.

The inter particle interaction is the real challenge I am having.

The example doesn’t do anything like that. I just though it might be helpful as a basic skeleton for a more advanced application.

Oh Thanks! Yeah I appreciate it. Always nice to have more things to reference. I haven’t really found any examples that do what I am trying to do and I have a feeling because it’s not an easy problem. But I feel like it should be possible

Alright, I uploaded the project to heroku/git

I hope that it runs fine for everyone, it works for me, but haven’t tested other browsers/gpus. All of the logic is in the index.html file, and the only shaders that are really relevant are the ones prefixed with ‘particle’.

EDIT: I just noticed that i am having problems with . the collisions fire for some but very few. Works fine in chrome/firefox. not a real issue, just something interesting.

https://pacific-hamlet-84784.herokuapp.com/

1 Like

I actually found out you can read from floating point textures, however it doesn’t seem to work in chrome. However I am having a ton of problems actually getting the implementation to work. If anyone has some time to take a look at it, it would be greatly appreciated.

Basically I am getting the texture to the fragment shader, however my particle collision checks aren’t working. I did a lot of debugging over the past few days and have gotten it so close but not quite there. I am having a few strange bugs. I will order anyone who helps a pizza <3 I am desperate at this point :frowning:

On a side note, I found that using i = i + 1 in a for loop throws an error while i++ does not
for(float i = 0.0; i < 10.0 ; i= i + 1.0)
vs
for(float i = 0.0; i < 10.0 ; i++)

the error is

[.Offscreen-For-WebGL-0x7ff3148afc00]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: Source and destination textures of the draw are the same.

ANYWAY, the problem I am having is that if I loop over my entire lookup texture, I am am able to get the correct results, so I know the values are stored in there correctly. The code I am using is the following

for(float j = -144.0 ; j < 144.0; j++){
 for(float i = -144.0 ; i < 144.0; i++){

  float  x_bkt_ind = (x_bkt_ind_start + i)/bucketsWidth;
  float  y_bkt_ind = (y_bkt_ind_start + j)/bucketsHeight;


  vec4 ind2 = texture2D( buckets , vec2(x_bkt_ind,y_bkt_ind) );

  if(ind2.z != 1.0 || x_bkt_ind < 0.0 || x_bkt_ind > 1.0 || y_bkt_ind < 0.0 || y_bkt_ind > 1.0 ){
    continue;
  }
  
   vec4 pos2 = texture2D( pos , vec2(ind2.xy)/res );

   vec2 diff = posi.xy - pos2.xy;

   float dist = length(diff);


  vec2 uvDiff = ind2.xy -  gl_FragCoord.xy ;
  float uvDist = abs(length(uvDiff));

  
  if(dist <= target && uvDist >= 0.5){
    float factor = (dist-target)/dist;
    x = x - diff.x * factor * 0.5;
    y = y - diff.y * factor * 0.5;
  }

  
 }
}

I read the pixel values out for the buckets and they all appear to be correct (between 0-144) which is why I am doing -144:144 as my range (to guarantee that I hit all of the pixels. once this works I will change it. The thing is, if I hardcode 70 as the bucket range (put it in the middle) the code works fine, however when I calculate it, it seems to break. This seems very strange to me because no matter what the bucket value, it should iterate over the pixels.