Particle Based Collision Detection on GPU - three.js

I am trying to make a particle based simulation using the Three.JS particle system. In order to control the vertices I am using fragment shaders so each index in the fragment shader is the position of the particle. I can get velocity from storing the old texture and computing the difference in position. The problem I am confused about is how I would implement collision handling between the particles.
Instead of having each particle go over every other particle in the array (which I can't imagine would work, since it would be like 1,000,000 checks per particle), I was thinking of grouping the points into grid cells and checking the adjacent cells (as I would do on the CPU), however I am unsure how to get group the particles on the GPU. I basically want a texture that is a grid that contains information about the particles that fall within the area that grid cell covers.
Any advice or strategies would be greatly appreciated!

Related

What is the most efficient way to create a reservoir in Three.js?

I am creating a 3D reservoir model which looks like this.
It's made of hundreds of thousands of cells with outline. The outline is needed for all cells underneath, because there is an IJK filter used to hide cells on any level and thus show the rest. Once the model is rendered, it shouldn't need to be updated in terms of position or scale.
That's enough about the background. The approach I'm using is creating one large geometry, which stores all vertices cross the reservoir in one triangle strip. It also stores IJK index for each cell, so the IJK filter works in shader level. This should create the mesh part. Then I create another object to draw all outlines using one THREE.LineSegments.
The approach works pretty well for small amount of cells, but for large data set, frame rate drops.
I'm proposing another way of doing this by barycentric outline and instancing drawing. Barycentric outline drawing removes the extra LineSegment object, since it draws outline in fragment shader. However, it comes with drawbacks. Because of the missing of geometry shader in WebGL, I have to use full triangle rather than triangle strip to store barycentric coordinates for each vertex. I'm ok with this extra memory usage, if instanced drawing can boost the performance.(?) That's to say, I draw a cube with outline, and I create as many instances as I need and put them in right position.
I am wondering if this approach is indeed gonna increase the performance theoretically. Any thoughts are welcomed!
Ok I think I am gonna answer this question myself.
I implemented the change based on above ideas and it works pretty good compared to the original version.
Let's put the result first: this approach has no problem rendering hundreds of thousands of cells at reasonable frame rate. My demo contains 400,000 cells, with the frame rate at 50 fps in worst case, running on my Nvidia 1050Ti card and 4k monitor. For comparison, if I draw 400,000 cells in the previous version, the frame rate could drop to 10 fps.
This means using instanced drawing for a large object is faster than composing a single large geometry. For rendering performance, the instanced cube is rendered only one side, while triangle-stripped cube is two-sided. Once I can draw a single unit cube with ideal outline, I can transform it to any places in "any" shape in vertex shader. But of course instanced drawing comes with its restrictions: each cell doesn't have to be at same shape, but has to have same number of vertices, faces, etc; I lost control to change vertex color...
As for memory usage, the new approach actually use less. I provide position for 8 vertices, instead of 14, in each cell. Even though the first unit cube has 36 vertices, I can use its unit position as index, for subsequent instances. That is, for 36 unit vertices (0/1, 0/1, 0/1), I only need to provide 8 real positions.
Hope this helps for people who want to implement the same optimization.

THREE.js adding bullets as sprites and rotating each individually

I have been working on programming a game where everything is rendered in 3d. Though the bullets are 2d sprites. this poses a problem. I have to rotate the bullet sprite by rotating the material. This turns every bullet possessing that material rather than the individual sprite I want to turn. It is also kind of inefficient to create a new sprite clone for every bullet. is there a better way to do this? Thanks in advance.
Rotate the sprite itself instead of the texture.
edit:
as OP mentioned.. the spritematerial controls the sprites rotation.y, so setting it manually does nothing...
So instead of using the Sprite type, you could use a regular planegeometry mesh with a meshbasic material or similar, and update the matrices yourself to both keep the sprite facing the camera, and rotated toward its trajectory..
Then at least you can share the material amongst all instances.
Then the performance bottleneck becomes the number of drawcalls.. (1 per sprite)..
You can improve on that by using a single BufferGeometry, and computing the 4 screen space vertices for each sprite, each frame. This moves the bottleneck away from drawCalls, and will be limited by the speed at which you can transform vertices in javascript, which is slow but not the end of the world. This is also how many THREE.js particle systems are implemented.
The next step beyond that is to use a custom vertex shader to do the heavy vertex computation.. you still update the buffergeometry each frame, but instead of transforming verts, you're just writing the position of the sprite into each of the 4 verts, and letting the vertex shader take care of figuring out which of the 4 verts it's transforming (possibly based on the UV coordinate, or stored in one of the vertex color channels..., .r for instace) and which sprite to render from your sprite atlas (a single texture/canvas with all your sprites layed out on a grid) encoded in the .g of the vertex color..
The next step beyond that, is to not update the BufferGeometry every frame, but store both position and velocity of the sprite in the vertex data.. and only pass a time offset uniform into the vertex shader.. then the vertex shader can handle integrating the sprite position over a longer time period. This only works for sprites that have deterministic behavior, or behavior that can be derived from a texture data source like a noise texture or warping texture. Things like smoke, explosions, etc.
You can extend these techniques to draw gigantic scrolling tilemaps. I've used these techniques to make multilayer scrolling/zoomable hexmaps that were 2048 hexes square, (which is a pretty huge map)(~4m triangles). with multiple layers of sprites on top of that, at 60hz.
Here the original stemkoski particle system for reference:
http://stemkoski.github.io/Three.js/Particle-Engine.html
and:
https://stemkoski.github.io/Three.js/ParticleSystem-Dynamic.html

How to store and access per fragment attributes in WebGL

I am doing a particle system in WebGL using Three.js, and I want to do all the computation of the particles in the shaders. To achieve that, the positions (for example) of the particles are stored in a texture which is sampled by the vertex shader of each particle (POINT primitive).
The position texture is in fact two render targets which are swapped each frame after being updated off screen. Each pixel of this texture represent a particle.
To update a position, I read one of he render targets (texture2D), do some computation, and write on the other render target (fragment output).
To perform the "do some computation" step, I need some per particle attributes, like its velocity (and a lot of others). Since this step is done in the fragment shader, I can't use the vertex attributes buffers, so I have to store these properties in separate textures and sample each of them in the fragment shader.
It works, but sampling textures is slow as far as I know, and I wonder if there is some better ways to do this, like having one vertex per particle, each rendering a single fragment of the position texture.
I know that OpenGL 4 as some alternative ways to deal with this, like UBO or SSBO, but I'm not sure about WebGL.

OpenGL performance issue

I'm writing a 2D RPG using the LWJGL and Java 1.6. By now, I have a 'World' class, which holds an ArrayList of Tile (interface with basic code for every Tile) and a GrassTile class, which makes the use of a Spritesheet.
When using Immediate mode to draw a grid of 64x64 GrassTiles I get around 100 FPS and do this by calling the .draw() method from each tile inside the ArrayList, which binds the spritesheet and draws a certain area of it (with glTexCoord2f()). So I heard it's better to use VBO's, got a basic tutorial and tried to implement them on the .draw() method.
Now there are two issues: I don't know how to bind only a certain area of a texture to a VBO (the whole texture would be simply glBindTexture()) so I tried using them with colours only.
That takes me to second issue: I got only +20 FPS (120 total) which is not really what I expected, so I suppose I'm doing something wrong. Also, I am making a single VBO for each GrassTile while iterating inside the ArrayList. I think that's kind of wrong, because I can simply throw all the tiles inside a single FloatBuffer.
So, how can I draw similar geometry in a better way and how can I bind only a certain area of a Texture to a VBO?
So, how can I draw similar geometry in a better way...
Like #Ian Mallett described; put all your vertex data into a single vertex buffer object. This makes it possible to render your map in one call. If your map get 1000 times bigger you may want to implement a camera solution which only draws the vertices that are being shown on the screen, but that is a question that will arise later if you're planning on a significantly bigger map.
...and how can I bind only a certain area of a Texture to a VBO?
You can only bind a whole texture. You have to point to a certain area of the texture that you want to be mapped.
Every texture coordinate relates to a specific vertex. Every tile relates to four vertices. Common tiles in your game will share the same texture, hence the 'tile map' name. Make use of that. Place all your tile textures in a texture sheet and bind that texture sheet.
For every new 'tile' you create, check whether the area is meant to be air, grass or ground and then point to the part of the texture that corresponds to what you intend.
Let's say your texture area in pixels are 100x100. The ground area is 15x15 from the lower left corner. Follow the logic above explains the example code being shown below:
// The vertexData array simply contains information
// about a tile's four vertices (or six
// vertices if you draw using GL_TRIANGLES).
mVertexBuffer.put(0, vertexData[0]);
mVertexBuffer.put(1, vertex[1]);
mVertexBuffer.put(2, vertex[2]);
mVertexBuffer.put(3, vertex[3]);
mVertexBuffer.put(4, vertex[4]);
mVertexBuffer.put(5, vertex[5]);
mVertexBuffer.put(6, vertex[6]);
mVertexBuffer.put(7, vertex[7]);
mVertexBuffer.put(8, vertex[8]);
mVertexBuffer.put(9, vertex[9]);
mVertexBuffer.put(10, vertex[10]);
mVertexBuffer.put(11, vertex[11]);
if (tileIsGround) {
mTextureCoordBuffer.put(0, 0.0f);
mTextureCoordBuffer.put(1, 0.0f);
mTextureCoordBuffer.put(2, 0.15f);
mTextureCoordBuffer.put(3, 0.0f);
mTextureCoordBuffer.put(4, 0.15f);
mTextureCoordBuffer.put(5, 0.15f);
mTextureCoordBuffer.put(6, 0.15f);
mTextureCoordBuffer.put(7, 0.0f);
} else { /* Other texture coordinates. */ }
You actually wrote the solution. The only difference is that you should upload the texture coordinates data to the GPU.
This is the key:
I am making a single VBO for each GrassTile while iterating inside the ArrayList.
Don't do this. You make a VBO once, and then you update it if necessary. Making textures, VBOs, shaders, is the slowest possible use of OpenGL--no wonder you're getting problematic framerates--you're doing it O(n) times, each frame.
I think that's kind of wrong, because I can['t?] simply throw all the tiles inside a single FloatBuffer.
You only gain performance when you batch draw calls. This means that when you draw your tiles, you should draw all of them at once with one VBO.
//Initialize
Make a single VBO (or two: one for vertex, one for texture
coordinates, whatever--the key point is O(1) VBOs).
Fill your VBO with ALL of your tiles' data.
//Main loop
while (true) {
Draw the VBO with a single draw call,
thus drawing all your tiles all at once.
}

Vertex buffer objects and glutsolidsphere

I have to draw a great collection of spheres in a 3D physical simulation of a "spring-mass" like system.
I would like to know an efficient method to draw spheres without having to compile a display list at every step of my simulation (each step may vary from milliseconds to seconds, depending on the number of bodies involved in the computation).
I've read that vertex-buffer objects are an efficient method to draw objects which need also to be sometimes updated.
Is there any method to draw OpenGL spheres in a way faster than glutSolidSphere?
Spheres are self-similar; every sphere is just a scaled version of any other sphere. I see no need to regenerate any geometry. Indeed, I see no need to have more than one sphere at all.
It's simply a matter of providing the proper scaling matrix. I would suggest a sphere of radius one centered at the origin for your display list or buffer object mesh. Then you can just transform it to different locations, using a scale to set the new radius.
I would like to know an efficient method to draw spheres without having to compile a display list at every step of my simulation (each step may vary from milliseconds to seconds, depending on the number of bodies involved in the computation).
Why are you generating a display list at all, if the geometry you put into is is dynamic. Display lists are meant for static geometry that never or only seldomly changes.
I've read that vertex-buffer objects are an efficient method to draw objects which need also to be sometimes updated.
Actually VBOs are most efficient with static geometry as well. In general you want to keep the number of actual geometry updates as low as possible. In your case the only thing updating are the positions (and maybe the size) of the spheres. This is a prime example for instanced drawing. However this also works well, with updating only a uniform or the transformation matrix and do the call drawing a sphere.
The idea of Vertex Arrays and VBOs is, that you draw a whole batch of geometry with a single call. A sphere would be such a batch.

Resources