Have you ever heard this story:
One man walks up to another man who is repeatedly hitting his head against a wall. The first man says, “Why are you doing that?” and the second man says, “Because it feels so good when I stop.”
Well, in my case, the "hitting my head against the wall" part was using OpenGl. In 5607, it wasn't so bad. Just make a VBO, and draw a few cubes and objects. This time, it made me want to burn my laptop in fury. However, when you have struggled for an hour trying to get just one thing to work right, or when your particle system has yet to actually render a single particle, even though you followed some silly tutorial to a point, and you finally figure out the solution, by yourself, there is no better feeling. The amount of relief that comes with figuring out the absolute Monster that is Opengl might be worth it. Here is my story of how I made Assignment 1 using OpenGl.
I started with my code for Assignment 4 of Csci 5607. In this project, I had rotational camera movement using the mouse and keyboard, a simple function for loading .obj files, a shader that could handle point & directional lighting, and a way to draw the .obj models to the screen. It wasn't too useful for particles, but it was a good starting point, and gave me the knowledge I needed with OpenGl to not want to die every time I typed the letters GL.
Working on getting my first particle to work was by far the worst part of this project. Thankfully it's what I started with, so things seemed like they could only get better after I finished them. Instead of using the same VBO I did for the 3D models, I decided to make an entirely new VBO for each particle system. the VBO would contain the vertices for all the particles in the system, and I would update the VBO each frame to modify the particles. Actually getting the VBO's to display on screen properly was the most frustrating part of the entire project. It's really hard to demonstrate your creative capacity, when you literally can't display anything on the screen. The moment when I saw the first large black square on my screen I almost cried. Even though it was not what I planned to display, and looked like crap. But actually having visual feedback makes modifying parameters so much easier.
Texturing the particles themselves wasn't actually that bad. I just made a separate shader for each particle system, and passed in quad texture coordinates.
The solution to this problem was quite simple. Use the CameraRight vector to determine the x values of the quad's corners, and add the CameraUp vector to determine the y values of the quad's corners. Discovering this trick was not so straightforward.
Transparency wasn't too bad. I just had to sort the particles from back to front. This was simplified by using C++'s std::vector class has a sort method.
Smoke was the easy one. All I did was spawn a bunch of large transparent particles, and make them move a tiny bit in a random direction each frame.
Making the magic system sucked. This was when I discovered that rendering two particle systems at once breaks everything. I didn't even have a hint at where to look for problems. The solultion was to simply pass the view and projection matrices to each of the particle system's shaders (I was only passing them to the most recent one). Simple solution, but it took forever to find.
The first magic system has 5 different spawn points, and each of them gravitate towards the center of the staff. The physics was a lot easier than I imagined.
The second magic system, if you would call it that contains only two particles. The only difficult part here was getting them to rotate along the axis they were moving in. I tried a bunch of techniques: Euler angles, Passing a rotation matrix to the vertex shader, even quaternions. But none of them did what I wanted. Thankfully I came up with a simple solution. I didn't need to rotate the particle, just the texture coordinates in the fragment shader. Four simple lines later and I had the exact effect I wanted (With a few visual fragments that I didn't bother fixing).
Only the first magic particle system. Changing OpenGl's default Blending mode made these look much more colorful.
Both Magic Particle Systems. The large red magic circle is intended to rotate around the axis of Megumin's Staff.
The simulation is a reference to the anime "Konosuba", in which one of the female leads Megumin casts a hilariously elegant explosion spell. While this is only 1 simulation, I believe the integration of 4 separate particle systems makes up for that.
I decided that instead of making a fire effect, an explosion effect would be more fitting. Changing the colors over time was the only challenge here, and it mostly came down to tuning them to change at the right time. Technically, the explosion effect is three particle systems in one, so my simulation in total has 6 different particle systems all taking place at once.
Here are the number of particles in each system:
On my laptop, the framerate is above 30FPS throughout the duration of the simulation. However, while recording using OBS studio, the framerate almost always falls below 30 FPS. This especially is the case while recording the explosion.
The magic Particle system can handle more than 10,000 particles at 30FPS, it just doesn't look very good.
Since I liked the way it turned out so much, I did a little bit of video editing to make a simple clip. I just wish I could record it at a reasonable framerate. I made a second video demo at a lower resolution which increased the framerate a little bit. It looks really cool when it plays at 50+ fps. It's a shame I couldn't record it at that framerate.
Here's the explosion with ~ 2000 particles instead of 20,000. Not as impressive, but I'm able to mostly get 30FPS while recording.
This code is a bit disorganized. Please let me know if you are looking for a piece of code and are unable to find it.
In the end, it was all worth it. I got a result that I think is cool. But I likely won't use OpenGL for future projects. It simply takes too much time to implement trivial effects. It should not take 3 hours to make an untextured particle system that doesn't display on the screen. I do like the speed and potential OpenGL has, and I will look for alternatives that keep that hope alive. This is why I will likely avoid Processing as well.
External References and Resources: