How To: Create a Simple Fireworks Effect in OpenGL and SDL

I’m teaching the programming stream for Diploma in I.T. – Multimedia at the moment, so we’re going to be making some simple games and things over the next couple of months, but to start them off we’re doing a little bit of work on particle effects because they’re simple and fun – you just write a single class which describes the properties and behavior of your particle, and then scale it up by adding a large number of particles to get some pretty nice effects.

So instead of doing a particle fountain, I thought some fireworks might be kinda neat… Take a swiz at the video below and see what you think!

Full C++ source-code available after the break for those of a curious nature =D

Download the file: Fireworks-with-Trails.cpp

Update: I’m not using SDL anymore, so I translated this into GLFW – much cleaner! The GLFW source code appears after the SDL version!
Update 2 – Nov 2012: Fixes to glfw version (removal of glee/glew, modification of accumulation buffer copying order).

GLFW Version (Fireworks class in separate files)

Firework.h

Firework.cpp

26 thoughts on “How To: Create a Simple Fireworks Effect in OpenGL and SDL”

    1. Hi Nikita,

      I’m not in the least bit angry – in fact, quite the opposite! I’m really glad that you found the code useful, and I put the source code up in the first place in the hope that it would be.

      Thanks for taking the time to post a comment, and for including me/this-post in your modified source. I hope that when you’ve finished it you’ll come back and post a link to the completed game.

      P.S. I used to play Nebulus back on the Spectrum when I was a kid (and then later on the Amiga) – great game! I hope you include the helloiamjmp cheat! =D

  1. Hi,
    Thanks for this great example. The high number of comments really helps to understand what is going on.
    I have one problem though, with the trails.

    At home I tried it at three different computer and none had any trails, not even when I just copied your code. However, now I tried it at work and here everything is as it should be, with nice trails behind the rockets.

    Is there any setting that controls this that I did not activate at home? The only obvious difference that I can make out between these PCs is the OS (Win7Home vs. Win7Pro) and of course some hardware (ATI Radeon card vs. nVidia Quadro FX).

    Thanks
    Frank

    1. Hi Frank,

      That’s pretty odd – try pasting the following code at the bottom of the setupScreen function to check that you’re getting an accumulation buffer created:

      When I add this code I get 16 bits each for Red, Green, Blue and Alpha – so try it on the machines where the trails don’t work to make sure you’re actually getting an accumulation buffer on ’em.

      Also, try the exact same executable that definitely works on your work machine on your home machines to rule out any code issues.

      Failing all that, I moved this code over from SDL to GLFW the other day but hadn’t got around to adding that code, but now that I have maybe you’ll have more luck with that =D

      Let me know how you get on =D

      1. Hi,
        I’ll add that code when I’m back at home later today.

        I used the very same executable on all machines (built at home, imagine my surprise when I started it here and it looked different).

        However, I think you’re right that I don’t have an accumulation buffer, as when I tried to change
        glClearAccum(0.0f, 0.0f, 0.0f, 1.0f);
        at home nothing changed, whereas here at work I get a nice colored background.

        Can it be that ATI does not support accumulation buffers on consumer cards? (I found http://forums.amd.com/game/messageview.cfm?catid=260&threadid=123808 which seam to have a similar problem).

        But I’ll try adding your code snippet just to be sure.

        Thanks
        Frank

  2. Hi,
    I tried the same executable on all machines – I emailed it yesterday to my work address just to give it a go, but was sure it will not show trails. Imagine my surprise when I started it and got the trails. All my home PCs have ATI Radeon cards.

    I just tried adding the code and I get all zeros.
    At work I spoke to our graphics guy and immediately after I mentioned that I have an ATI card he said he knows the problem.
    We use nVidia quadro cards at work because they have the best openGL support. According to him even the ATI FirePro cards have rather sub-par openGL support, never mind the consumer ones.
    I had a play with an updated card driver version, but it did not change anything.

    However, after knowing this I just made an experiment and undusted my old laptop from the medieval era, which has a nVidia geforce go card. It plays the fireworks with about 1fps (tops), but there are nice trails.

    So I fear I am stuck without trails, unless there is a way to get these effects without accumulation buffer?

    Thanks
    Frank

    1. Okay, so if you get all zeros for the accumulation buffer bits on the ATI cards you’re definitely not getting an accumulation buffer, hence no trails. Makes sense ;)

      As for other ways of creating the trails, you just need some kind of buffer that you can use for temporary storage. In essence, we just need somewhere to store a copy of what was on the screen so we can:
      – Clear the screen
      – Draw what used to be there but with a little less opacity
      – Draw the elements of our new frame on top of it

      Probably the best way to go about this would be to copy to and from a Frame Buffer Object, but FBOs can be tricky if you’ve not worked with them before (which I haven’t, although I’ll be learning them soon!).

      Another alternative might be to NOT clear the screen, but instead draw a full-screen quad with low opacity over the top of everything just before drawing your new frame… I thought this would work, but wasn’t 100% sure – but guess what? It does =D

      Here’s the important stuff to make it happen:

      Another thing you might want to try is blurring the entire scene before drawing your new frame, which’ll give you an effect like this: Per-Pixel Collisions (uses blur filter on the stage instead of clearing it), although I’ve not used any blur filters in OpenGL yet, so you’d be on your own there.

      Anyways, hope this helps!

      1. Hi,
        with that modification it now works as it should, thanks.
        I think I’ll stay clear of FBOs for the moment, enough other things to understand first – this is my first experiment with openGL, so I still have a good way to go :)

        Thank you for your help!

        Frank

      1. Sounds good.. :) I’m start learning OpenGL ES too and I would greatly appreciate your help about opengl es and how to draw this nice particle effect.
        Your blog is already bookmarked and in my NetNewsWire month ago ;)
        Thank you .

  3. Hi there,

    I am trying to run your code but I got a bunch of errors. Some are for linker and the other is for checkGLError(“InitGL”);.

    I tried to insert all the lib and ddl but nothing.
    Can you help?

    Thank you

    1. There’s a couple of problems with the code as it turns out – I’ll clean it up and upload a self-contained Visual Studio 10 version this evening (Australian time).

      1. I fixed the code in the post, and here’s a completely refactored and improved C++ version for Visual Studio 2010. It doesn’t use GLEW or GLee at all – just GLFW, and comes with the libs to run from VS2010: Fireworks-Nov-2012.zip.

        Best wishes,
        r3dux

        (Didn’t get it done last night as I was down in Melbourne seeing the mighty Radiohead @ Rod Laver arena ;-) )

  4. Greetings. Attempting to utilize your firework program in order to create working explosions for my game senior project. Having trouble because, when compiling, it says that GLint and GLboolean are not valid types. Don’t know how to fix this. Please reply ASAP.

    1. The GLxxx types are just typedefs which can aid portability of programs between platforms, and they should be defined in GL.h (on my Windows machine this equates to C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\gl\GL.h).

      So either include the file with:

      or, you could just replace GLint with int, GLboolean with bool etc.

      1. Me again. It started giving me those errors with the header file because it wouldn’t properly read the members when including gl.h directly. I thought it would be fixed by instead changing it to include glfw.h in there, but instead it gave me a whole ton of linking errors in Fireworks-with-Trails.cpp.

  5. Hello again. For some reason, having trouble linking GLFW to the main program., even though I’m sure that I have it properly included in my Visual Studio 11 folder. Can you offer any help as to sorting this? I’d try using the GLFW walkthrough, but I have no complete idea what to do since I don’t use any of the compilers it mentions besides Visual Studio.

    1. To link in GLFW you need the header file (glfw.h) and the lib (GLFW.lib).

      The easiest way to link them is to just place both files in the same location as your main.cpp file, then add the lines:

      and the opengl and glfw libraries with:

      So you’ll end up with something like this:

      Instead of using the pragma directive you can add in the library name yourself by going to:
      Project | [your-project-name] properties, and then in the Configuration properties | Linker | Input | Additional Dependencies text box you can add in the name of the library/libraries you want linked in. But generally I find the pragma directive works fine.

      Cheers!

  6. I don’t think there’s an accumulation buffer available in OpenGL ES (or not in early versions) – but there are a few ways to get trails.

    The easiest would be to NOT clear the colour buffer between each frame drawn, and instead draw something like a 20% opacity black quad over the top of everything – this would give you 4 frames worth of trails as previous drawn things go 80/60/40/20/00 percent transparency. You’d still want to clear the depth buffer properly if working in 3D.

    Another way is to have a series of ‘rolling’ render buffers, and render each frame to a different buffer – so, for example, if you had 3 render buffers you render to 0 then 1 then 2 then 0 then 1 then 2… To get the trail effect you simply combine (average) each frame. There’s a good example of this in the OpenGL Superbible 4th Edition.

    Unfortunately I have no OpenGL ES code for any of this, and don’t use iOS at all!

  7. Dear Sir r3dux,

    I really like the algorithmic process you have incorporated into this wonderful fireworks display given the elegant physics you have demonstrated to achieve a dramatic and realistic particle system which mimics a fireworks phenomenon. I have a question since I cannot see it mentioned.

    What license is this source code licensed under. I would be very interested in using it as a congratulations background demo screen for one of my puzzles. However I would like your permission to do this and of course, I would be happy to include your name as a contributor of the solitaire game (author of the animation) on the credits screen.

    1. Hi Cero – I’m glad you liked the fireworks effect, there is no specific license on the code, which I would imagine places it into the public domain by default.

      Please feel free to use the code in whatever way you’d like for any purpose at all.

      You don’t have to give me a credit in your game, but if you’d like to that would be very nice of you.

      One thing you might like to fix is that the shape of the fireworks explosion is somewhat “square”, because the the direction for the firework particles is a random value between -4.0f and +4.0f (lines 75 & 76 in Firework.cpp). What you really need to do is normalise the vector made by the horizontal and vertical directions (i.e. so it has a ‘unit length’ of 1.0f) and then scale it up so the particles move at the speed you want (i.e. multiply by 4.0f in this case).

      If you’re having any trouble implementing this then I’m happy to help, but do have a crack at it – learning is fun =D

      Cheers,
      r3dux

Leave a Reply

Your email address will not be published.