Efficient particle system in javascript? (WebGL)

╄→гoц情女王★ 提交于 2019-12-02 21:12:48

you should never draw primitives individualy. Draw them all at once, whenever possible. Create an ArrayBuffer that contains position and other necessary attributes of all particles and then draw the whole buffer with one call to gl.drawArrays. I can't give exact instructions because I'm on mobile but searching for vbo, interleaved arrays, and particles in opengl will surely help you find examples and other helpful resources.

I'm rendering 5m static points that way with 10fps. Dynamic points will be slower as you'll have to continually send updated data to the graphics card but it will be way faster than 15fps for 10000 points.

Edit:

You might want to use gl.POINT instead of TRIANGLE_STRIP. That way, you only have to specify the position and and gl_PointSize(in the vertex shader) for each square. gl.POINT are rendered as squares!

You can take a look at the source of these two point cloud renderer:

  • https://github.com/asalga/XB-PointStream
  • http://potree.org/wp/download/ ( By me, following files might help you: WeightedPointSizeMaterial.js, pointSize.vs, colouredPoint.fs )
  • It depends on what you are trying to do. When you say "gravity" to you mean some kind of physical simulation with collisions or do you just mean velocity += acceleration; position += velocity?

    If the latter then you can do all the math in the shader. Example is here

    https://www.khronos.org/registry/webgl/sdk/demos/google/particles/index.html

    These particles are done entirely in the shader. The only input after setup is time. Each "particle" consists of 4 vertices. Each vertex contains

    • local_position (for a unit quad)
    • texture_coord
    • lifetime
    • starting_position
    • starting_time
    • velocity
    • acceleration
    • start_size
    • end_size
    • orientation (quaterion)
    • color multiplier

    Given time you can compute the particles's local time (time since it starts)

     local_time = time - starting_time;
    

    Then you can compute a position with

     base_position = start_position + 
                     velocity * local_time + 
                     acceleration * local_time * local_time;
    

    That's acceleration * time^2. You then add the local_position to that base_position to get the position needed to render the quad.

    You can also compute a 0 to 1 lerp over the lifetime of the particle

     lerp = local_time / lifetime;
    

    This gives you a value you can use to lerp all the other values

     size = mix(start_size, end_size, lerp);
    

    If the particle a size of 0 if it's outside the it's lifetime

     if (lerp < 0.0 || lerp > 1.0) {
       size = 0.0;
     }
    

    This will make the GPU not draw anything.

    Using a ramp texture (a 1xN pixel texture) you can easily have the particle change colors over time.

     color = texture2D(rampTexture, vec4(lerp, 0.5));
    

    etc...

    If you follow through the shaders you'll see other things similarly handled including spinning the particle (something that would be harder with point sprites), animating across a texture for frames, doing both 2D and 3D oriented particles. 2D particles are fine for smoke, exhaust, fire, explosions. 3D particles are good for ripples, possibly tire tracks, and can be combined with 2D particles for ground puffs to hide some of the z-issues of 2D only particles. etc..

    There are also examples of one shots (explosions, puffs) as well as trails. Press 'P' for a puff. Hold 'T' to see a trail.

    AFAIK these are pretty efficient particles in that JavaScript is doing almost nothing.

    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!