The Temple of Whollyness

Learning Open Frameworks

This post originally appeared on the whoisowenjones.com blog.

lucas-learns-openframeworks-2

As part of my learning-is-the-new-black 2014 initiative, I’ve decided to learn languages by creating small projects. I limit my time in the language to a week and share the results. This year’s first undertaking is all about openFrameworks, an open-source C++ toolkit, and, after an Inspiration Friday and a few evenings, I was able to create this video:

Day 1 – Planning and Installing

My projects always start as visual in my mind, and the reason I wanted to learn OF was because it’s C++ based which makes it’s much, much faster than what I can do in the browser. I wanted to create a sense of organic movement with particles, and leverage blend modes to make it look like overlapping particles emit light. A fancy screensaver, if you will.

The first step was installing openFrameworks and following tutorials to get a grasp of the language and environment. The OF team has done a great job documenting the installation process and also has some fantastic demos which got me up and running, relatively quickly, but not altogether smoothly. I had issues related to my limited exposure to Xcode, which has its own learning curve for a web developer, but the biggest stumbling block is what appears to be some incompatibilities with Xcode 5.0.2. On more than one occasion, I totally bricked my project, and could not undo to a previous working version. I decided that Day 2 would be about connecting Xcode to git and doing frequent commits. Fortunately, OF includes a project generator that does a lot of the heavy lifting of creating a new project for you, so it wasn’t problematic to go through the process, even multiple times, to figure out where I went astray.

After reading the forums, I was able to compile a new project based on the examples in the graphics folder. My example was simply a single particle that followed the mouse. It’s essentially the Hello World of creative coding, but I was still pleased to be saying hi in a new language (OF) in a new country (Xcode).

Day 2

One thing I dislike about javascript is how loose it is. I really like interfaces and strict typing and inheritance, and OF definitely makes use of those. So it’s only natural that the control-nerd in me demanded I turn the particle from Day 1 into its own class with a small set of methods. The two methods of my particle are moveTo(int x, int y), and draw().

But my favorite part of creating a particles class is that I can now iterate the list of particles as a vector, which is much faster than looping over an array. This line of code makes me really happy:

for (vector::iterator theBall = balls.begin(); theBall != balls.end(); ++theBall) {

I also took some time to read about connecting Xcode to a git repo, and once I had a successful commit, I called it a day. While it was a little disparaging to know that the output of Day 2 looks the exact same as Day 1, I knew I had built infrastructure that would hopefully be enough to help me create something beautiful by Day 5.

Day 3

My goal for Day 3 was to create hundreds of particles to test performance and to tweak the motion of the particles so they would move be attracted to the mouse cursor with something other than a linear (ahem, boring) force.

Tweaking the way the particles move was lots of trial-and-error, but insanely fun. Here’s where you get your trig on and wish you had paid more attention in high school. I’m using a combination of forces that push the particle around based on each particle’s unique angle, velocity, and – this one’s important – the distance from the mouse cursor. The further away a particle is, the less the other two forces are affected, meaning close-in particles move faster than far away ones. This gives the particles a graceful accelerating/decelerating motion which I find quite pleasing. Here’s where I discovered the ofMap function which I’ll be rolling into my javascript library. It’s a super useful function, and such an obvious candidate for being a function.

Once I was pleased with the organic motion of a single particle, I simply needed more of them! I thanked myself for creating the a particle class yesterday because creating multiple particles was quite trivial. I could instantiate on mouse click, and my ofApp class gained an addBall method that I could summon repeatedly. I also tweaked the mouseReleased and mousePressed methods so the longer I was holding the mouse button down, the more particles would be created. I immediately saw the need to clear the particles as restarting the app is a cumbersome way to clear the screen, so a clear() method came next.

Day 4

Although performance wasn’t an issue, I felt a little dirty not taking advantage of drawing with the GPU. The idea here is if you draw to a GPU buffer and then push that to the screen, it’s much faster than drawing straight to the screen. This forum post came in handy with the right settings.

I could now have thousands of particles moving around and was pretty pleased with my progress. I only wanted to tweak the colors, use a blend mode, and perhaps figure out how to blur the background. This turned out to not be as simple as I thought, and I only barely finished.

The problem I kept running into was the particles looked washed out. I could get vibrant colors, or I could get lower alphas, but I could not seem to get vibrant colors AND lower alphas at the same time. I call this the watercolor loop, where the transparency increases as saturation decreases. Oddly, I also had better luck on white than on black. I eventually resolved this by using GL_RGBA which has 32 bits of red, green, blue, and alpha available. I eventually unlocked the right sequence of steps to start drawing to the GPU, enable alpha blending, set the blend mode, draw each particle, then disable the blendmode (with the suspiciously named ofEnableBlendMode(OF_BLENDMODE_DISALBED), and then disable the alpha blending. The weird part was I ended up adding a fill of white over the entire FBO and then stopping the GPU drawing. I still don’t totally have my head around that step, but if I remove it or change the fill, then only certain channels come through.



    rgbaFboFloat.begin();
    ofEnableAlphaBlending();

    // darkens the background
    ofFill();
    ofSetColor(0, 0, 0, 5);
    ofRect(0, 0, ofGetWindowWidth(), ofGetWindowHeight());

    ofEnableBlendMode(OF_BLENDMODE_ADD);

    for (vector::iterator theBall = balls.begin(); theBall != balls.end(); ++theBall) {
      theBall->draw();
    }

    ofEnableBlendMode(OF_BLENDMODE_DISABLED);
    ofDisableAlphaBlending();

    ofFill();
    ofSetColor(255,255,255);
    rgbaFboFloat.end();

At that point I called it a night.

Day 5

My final day on the project was spent on implementing a blur so the background blurs out as it fades away. I came across an OFXFBOBLUR github which sounded promising and delivered. I spent the rest of the night, literally hours, watching the app run. I became fascinated with the way the particles faded away, especially in areas where multiple particles overlapped and illuminated an area, then faded away in an entirely unpredictable manner. It’s exactly what I had in mind when I started the project. Success!

lucas-learns-open-frameworks-3 lucas-learns-openframeworks-2