Boids Simulation

This is an experiment of using compute shader in OpenGL to simulate Boids behavior. The demo above shows a simulation, comprising of 16,384 agents (boids).

To draw that many boids on the screen, I also used the batch rendering technique.

Batch Rendering

Originally, the way I rendered the boids was to iterate over every boid to make a draw call. That means for a simulation with 16 thousand boids, there were many, many draw calls. The frame rate was fairly miserable because of that.

The idea was to reuse the same collection of vertices and calculate a different model matrix in the vertex shader.

(FYI, the code above uses some custom wrapper functions. The renderer.Draw is equivalent to glDrawElements which issues one draw call.)

To achieve one draw call for all boids, I need to batch all their vertices into one Vertex Buffer Object and draw them all at once. So that I can do the following:

It is fairly easy as I only need to copy the original set of vertices of a boid for however many boids there are into the new VBO, and figure out the currect Index Buffer to draw all of the triangles.

The hard part is that now all the boid meshes are in the same place. Their positions need to be updated. I could update them on the host program before making a draw call, but that could be slow.

Again, I opted for using a unique model matrix for each boid in the vertex shader. That means all the boid meshes are still in the same location as represented in the VBO, but each of them will use a different model matrix.

This time, however, the model matrix cannot be a uniform since a uniform can only be updated between draw calls.

What I did was for each vertex, I calculated its corresponding model matrix in the vertex shader. The catch is that each vertex will now need to contain an index in its vertex data that tells which boid it belongs to. I can then use this index to fetch the right positional data from the SSBO and make the consequent calculation for the model matrix.

Future Improvement

I think a more optmized way would be to calculate the model matrices in the compute shader and store them into an SSBO. This is because each boid, which has 5 vertices as a pyramid shape, will be calculating the same model matrix five times using this current method. It is wasteful considering the calculation also contains some expensive operation such as normalizing a vector and division.

However, if I caculate the model matrices in the compute shader, not only can I have each invocation do its own calculation in parallel with others, but they also just have to do it once each. (An invocation is responsible for calculating the position, velocity and acceleration of a boid. It will also be appropriate for an invocation to calculate the model matrix that represents its boid.) Finally, in the vertex shader, I just need to fetch the corresponing and calculated model matrix.

Next
Next

The Odessa Tree