Today we are opening the openFrameworks donations page!
For years we’ve developed openFrameworks through the voluntary, non-paid contributions of many people around the world.
These contributions are often part of the process of people using openFrameworks for their work or practice. As they discover bugs or need new features, they contribute these changes back to openFrameworks, benefiting the community and project as whole.
This workflow has worked fairly well for openFrameworks up to this point. However it means that the growth of the project is limited by the particular interests and available time of contributors and has meant that some areas of the project have fallen behind.
We are opening up the donations page to fund some of these areas and to help OF continue forward in a more sustainable way. Your donations will contribute to the following:
Documentation
Documentation is one of the main areas that has been behind the rest of the project. We think that it could be that the users who are confident enough to contribute to the openFrameworks codebase don’t rely as much on the the documentation and the people who do rely on it and run into unclear or missing documentation usually don’t feel confident enough to contribute to it.
We’ve organized documentation sprints which has been helpful in the short term, but it doesn’t take long for the documentation to begin to drift out of sync with this codebase and as it is an area where there isn’t active ongoing contributions we believe it needs us to take a different approach.
With financial contributions from individuals, companies and institutions we would be able to fund a team, over the long term to work on the documentation, make sure it was up to date with the API and provide good examples and tutorials for all areas of the project.
Infrastructure
As the openFrameworks project has grown we are relying on wide range of services and infrastructure to keep the project running. We have a distributed build system, continuous integration services ( CI ) that allow us to check that changes don’t break the codebase and a tool for compiling all the libraries for the many different platforms OF supports ( Apothecary ).
There is also a lot of work that needs to be done not directly related to using OF itself, like maintaining the forum, updating the CI or fixing the multiple servers we use when something breaks, as well as keeping them up to date. Maintaining these services and development systems is something we’ve been doing up until now unpaid, but the amount of time it requires isn’t sustainable to continue in the long term.
Diversity
Making openFrameworks more accessible and the community of users more diverse is another big goal of the project that we think we can really improve if we have a significant and ongoing financial contribution.
Until now we’ve been relying on a community of contributors who had enough free time to work on the project but we've come to realize that because of very different factors like for example, wages inequality, it is much harder for some people like women, people of color or people living in developing countries to work without being paid in their free time. By being able to pay for some contributions we expect to help overcome that barrier and increase range of people contributing and shaping the future of openFrameworks.
A more sustainable model
Opening up the donations page is only a first step. We are currently working on the outline for a more sustainable model for openFrameworks, which would allow the project to get broader, institutional level funding. Individual donations in the meantime will help immensely with us moving quicker towards our goals, offloading work onto a more diverse group of contributors and help achieve more regular, higher quality and better documented releases.
To donate
If you have used openFrameworks in your personal practice, or you represent a studio or company that has used openFrameworks in your work and you would like to financially support the project, please do so now at the donations link below.
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality
Anya is LIVE right now
FREE
Free to watch • No registration required • HD streaming
OpenGL Mathematics GLM has become the defacto standard for graphics vector math in C++ in the latest years. It's syntax mimics that of glsl so working with it while working with OpenGL, shaders... makes things easier cause the syntax is almost the same across the different languages.
openFrmaeworks, since version 0.10 uses GLM as it's default vector math library in the core and although old projects using ofVec* classes should work with minimal changes, if you are starting a new project we recomend to use GLM instead.
Namespace
GLM classes and functions are in the glm namespace so to use them you need to either prefix them with glm:::
glm::vec3 v(2.f, 2.f, 2.f); float l = glm::length(v);
Or in your .cpp files import the glm namespace at the very beginning:
using namespace glm;
And then use the classes and functions without prefix:
vec3 v(2.f, 2.f, 2.f); float l = length(v);
Functions not methods
GLM classes like vectors, matrices or quaternions don't have methods. Instead glm uses functions to operate on those classes so if you want to for example normalize a vector you would do:
glm::vec3 v(2.f, 2.f, 2.f); glm::vec3 n = glm::normalize(v);
The only exceptions to this rule are operators which you don't use directly but instead allow to do arithmetic operations so you can do things like:
GLM vector have a static length function which returns the dimension of the vector type, so glm::vec2::length() returns 2, glm::vec3::length() returns 3...
Because C++ allows to call static methods on instances of that class you can make the error of calling:
Mostly when porting old code form ofVec to glm, because ofVec included such a method, it's easy to try and call that function which will compile without errors but won't do what you expect.
When doing that, most modern compilers should show a warning because of calling a static method on an instance instead of a class, so be on the look for those when porting old code to GLM.
Type strictness
glm has a strict type system, similar to how things work in glsl, meaning that you can't autoconvert from one type to another automatically as it was the case with ofVectorMath.
GLM has some useful constants but the way to use them might be a little bit weird at first. The main problem comes from the fact that this constants are defined as templated functions so to call them you need to specify the type as in:
float p = glm::pi<float>(); double dp = glm::pi<double>();
Multiplication order
Finally, if you are used to the old openFrameworks vector math classes you would multiply vector and matrices like:
ofVec3 v; ofVec3f projected = v * model * view * projection;
with glm as in glsl the multiplication order is the oposite so now you would do:
Many OpenFrameworks Android apps are composed from a single activity, which derives from OFActivity and allow you to draw GL content in a canvas. This fits most cases. However, sometimes you need multiple activities, some with GL drawing and some without. OpenFrameworks Android supports such cases.
Add application initialization code
We can distinguish between application initialization and gl initialization. There are two methods in main.cpp, one for each. In most cases, there’s nothing to do in ‘ofAndroidApplicationInit’, and in ‘ofAndroidActivityInit’ we initialize the ofApp class.
‘ofAndroidApplicationInit’ allow you to do some initialization when the cpp side is created, even if the first activity is not a gl activity (for example, a completely native splash activity).
‘ofAndroidActivityInit’ is called when the gl canvas is initialized. This happens when the first OFActivity is created. Notice that if a second OFActivity is created on top of it, the canvas is recycled and this initialization code is not called again. However, if all OFActivites are destroyed, the canvas is indeed destroyed so when a new OFActivity is created, ‘ofAndroidActivityInit’ will be called again. The default implementation for this method instantiates the ofApp class, but you can add more code to it as needed.
Note that due to current architectural constraints, all activities share a single ofApp class and a single canvas. You cannot switch to different ofApp classes for drawing different activities as OpenFrameworks cannot currently hold multiple instances of the ofApp class in memory. It is up to you to signal the cpp side when a different activity is shown (when onResume is called on that activity), and perform different update/draw code to draw different content on the canvas.
Customizing the Android activity
OpenFrameworks supplies a base activity called OFActivity when the following conditions suits the project:
1) The first activity is this activity, meaning, the first activity in the application shows a gl canvas. 2) You want your activity to inherit from regular Android Activity class.
However, OpenFrameworks allows for more complicated scenarios, like having the first activity initializing the cpp side, but not the gl drawing (the first activity doesn’t draw gl at all, for example, a simple splash activity) or inheriting your activities from other classes, for example AppCompatActivity.
In order to achieve one or both the objectives above, you need to notify OpenFrameworks yourself on certain events, just like the original OFActivity does it:
In ANY activity in the application:
1) Whenever ANY activity is created OR resumed, you need to notify OpenFrameworks about it by calling OFAndroidLifeCycle.setActivity with this activity. 2) On the first activity created, you need to call OFAndroidLifeCycle.init() in order to initialize the cpp side. If this activity SHOULD NOT draw GL, you should call it with the parameter false in order to postpone canvas initialization.
In gl drawing activities:
1) in onCreate, call OFAndroidLifeCycle.glCreate() 2) in onResume, call OFAndroidLifeCycle.glResume() 3) in onPause, call OFAndroidLifeCycle.glPause() 4) in onDestroy, call OFAndroidLifeCycle.glDestroy()
You can look at the original OFActivity as a reference, and there’s also a detailed example with multiple activities in the android examples folder, called androidMultiOFActivityExample.
Transform feedback is a relatively new feature in opengl (present since 4.3 and so not available in macos). It allows to store the output of a vertex, geometry or tessellation shader into a buffer object.
For example we can draw a sphere in an ofVboMesh, draw it using a vertex shader that deforms the vertices using a noise function and get the result in a new buffer, then we can assign that buffer to an ofVbo for drawing.
This allows to do expensive transformations in the GPU only once, store them and then draw them instead of having to do the calculations every frame.
It also allows to do several steps of vertex shaders for example or to generate geometry with a geometry shader and then use a different vertex shader to draw...
The download for 0.10.0 for windows and linux, includes an example explaining how to use it in gl/tranformFeedbackExample
That example generates a mesh with a certain number of points but without setting them at all then draws the mesh using a shader with a transform feedback which modifies the poitns to distribute them along the surface of a semi-sphere uniformly and sets each vertex color depending on their position.
The resulting buffer is assigned to a vbo and drawn later in the draw function without having to calculate the positions every frame.
GL debug callback
OpenGL provides an extension (promoted to core in 4.3, which again means it won’t work in macos) that allows to debug the context for errors.
In OF 0.10.0 you can now call:
ofEnableGLDebugLog()
And if any error or any other internal message happens you'll get a debug trace in the console. You can even set a breakpoint while debugging inside ofGLUtils.cpp in the function gl_debug_callback to know which call is producing the message. Once the breakpoint is set the debugger will stop whenever a message happens and you can see in the stacktrace the original in your code that is triggering it.
This is useful to debug obscure GL bugs like buffers not correctly bound or similar problems which are really hard to debug usually.
To disable the logging you can call:
ofDisableGLDebugLog()
Custom materials extensions
ofMaterial, when used with opengl version 3 or more runs internally a glsl program that calculates the phong shading per fragment using all the lights enabled at that moment.
Sometimes we want to change the behaviour of that shader. To do so, since 0.10.0 you can setup a material using ofMaterialSettings and there specify a function which will be called after the lighting has been calculated. It receives the final color of the fragment as parameter and returns the modified color which will be the final color assign to that fragment:
That function has access to all the uniforms and varyings available in the fragment shader but we can also specify additional uniforms by using customUniforms in ofMaterialSettings and then setCustomUniform* while we use the material.
There's more information in the header of ofMaterial and soon in the online docs in the OF site
So when creating an instance of that class it would listen to the mouse and when the object is destroyed it’ll remove itself as a listener so there’s no calls once the object has been destroyed, otherwise we would get a crash.
The circle won’t receive the events anymore cause the copy won’t be listening to events anymore and the original will be destroyed as soon as we go out of setup.
Even worse if we try to put this class in a vector as before but register the event after we add it like:
The vector will move it's objects in memory when it runs out of contiguous memory which will make the address for our objects stored in the event invalid so we will likely get a segmentation fault and the application will crash.
By the rule of 3 (the rule of 5 since c++11) https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) when we add a destructor as we did above we should also implement a copy constructor and equal operator.
Doing so would solve our problem if in the copy constructor we re-add the new copy as a listener as well. But introducing a copy constructor is error prone since from now on we’ll need to copy every new member we add to the class.
To solve this issues in 0.10 we’ve introduced a new way to listen to events: ofEventListener. Now to listen to an event the preferred method is something like:
The listener will now auto unregister itself when the object is destroyed so there's no need for a explicit destructor. Also ofEventListener forbids to copy (or even move) an instance of a class containing it so if you now try to put a class listening to an event into a vector you'll get a compiler error.
You can still work around it by creating your copy/move constructors and equal operator but at least the error happens at compile instead of at run time.
It's still not recommended to implement copy constructors since it's really error prone and difficult to maintain. Instead if you want for example a collection of objects that listen to an event like the above you can put them in a collection that won't move it's elements in memory as a vector does, like a list or a deque and create them using emplace_backinstead of push_back:
std::list<CircleMovingWtihMouse> circles; objects.emplace_back(); // This crreates a new object in the list objects.back().doSomething(); //This calls a method on the last element added to the list
There's some limitations to this collections, for example you won't be able to access a random position on a list, only to iterate thorough all it's elements as in:
for(CircleMovingWtihMouse & o: objects){ }
And you won't be able to remove a random position of a deque containing listeners cause it would need to move it's elements in memory and the ofEventListener forbids that to avoid illegal memory accesses.
Another way to work around this is to wrap the objects in a smart pointer before putting them in a vector but be aware that doing so allocates every object in non contiguous locations in the heap so some of the advantages of using a vector are lost.
In general this new way of using events won't let you do anything that might crash or have an undefined behaviour.
If you need to add more than one listener to a class you can also use ofEventListeners:
Key event arguments now carry much more information than before. Until now a key event was just an integer with the ascii for the pressed key but from 0.10.0 and in line with our effort to support UTF8 across the core it now looks like:
class ofKeyEventArgs{ public: /// For special keys, one of OF_KEY_* (@see ofConstants.h). For all other keys, the Unicode code point you'd expect if this key combo (including modifier keys that may be down) was pressed in a text editor (same as codepoint). int key; /// The keycode returned by the windowing system, independent of any modifier keys or keyboard layout settings. For ofAppGLFWWindow this value is one of GLFW_KEY_* (@see glfw3.h) - typically, ASCII representation of the symbol on the physical key, so A key always returns 0x41 even if shift, alt, ctrl are down. int keycode; /// The raw scan code returned by the keyboard, OS and hardware specific. int scancode; /// The Unicode code point you'd expect if this key combo (including modifier keys) was pressed in a text editor, or 0 for non-printable characters. uint32_t codepoint; /// If this is a repeat event bool isRepeat; /// Key modifiers int modifiers = 0; bool hasModifier(int modifier){ return modifiers & modifier; } }
You can keep using ofKeyEventArgs::key as before but if you want to listen for keypresses to create a text you should use ofKeyEventArgs::codepoint which holds the utf8 code of the key except in the case of special keys like OF_KEY_SHIFT, OF_KEY_CONTROL, ... where it's equal to 0.
Also when you receive a key event you can also check if a modifier is pressed at the same time using ofKeyEventArgs::hasModifier() as in:
The callbacks in ofApp are still the simple ones that just receive the int key for key events and the position x and y and mouse button for mouse events but you can easily change them to:
and it'll just work without having to explicitly listen to that event. For any other class but applicaiton instances started with ofRunApp you'll need to register an event using newListener (or ofAddListener / ofRemoveListener)
Lambda functions
And finally since 0.10.0 you'll be able to use lambda functions to listen to events instead of having to create a specific method as in:
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality
Anya is LIVE right now
FREE
Free to watch • No registration required • HD streaming
In 0.10.0 there’s (finally) full support for UTF8 both as utilities to manipulate strings but also in ofTruetypefont.
String manipulation
Some of this utilities where already introduced in 0.9.0 but there's some more now and the API has been cleaned to make it more consistent.
All this functions start as ofUTF8* and if you want to do something with text which might have characters other than ascci, because UTF8 has variable length characters you should be using this functions instead of the corresponding string methods. for example instead of doing:
str.insert(pos, chr);
to insert a character you should be using:
ofUTF8Insert(str, pos, chr)
or when creating a string from keypresses:
ofUTF8Append(str, key);
there's also ofUTF8Substring, ofUTF8ToString and ofUTF8Length
Also to iterate over a string don't iterate over it's characters but use:
Let us know if any of them is wrong or you want us to add any that is missing!
There's still one thing that is not working yet, ligatures, some alphabets like arabic join some combinations of characters, that's still not working but there's tools that you can use to reshape the text and paste it into you OF code (like: http://mpcabd.xyz/python-arabic-text-reshaper/). We'll try to figure this one out for next release
Arturo
ps: Thanks to Hiroshi Matoba for his help with the Japanese example and figuring out a couple of missing characters in the Japanese alphabet
The first post in the series about the new features in the 0.10.0 release, is going to be a short one about the gui.
Color picker
Up until 0.9.8 editing colors in the gui could only be done by adjusting the different rgb values using individual sliders which was not very intuitive:
In 0.10.0 it looks like this:
The new color picker is based on ofxColorPicker by Lukasz Karluk adapted to work with ofxGui and ofParameter
Text fields
In 0.10.0 ofxGui will add a text field for any ofParameter or you can create it manually using ofxInputField.
This new control is based on the original ofxInputField by Felix Lange with additions to better support selection, utf8 and clipboard.
Additionally any slider can be turned into an input field temporarily by right clicking on it, allowing for much more precise input.
Apart from this, one can now add an ofParameter<void> in a parameter group to get a button, add listeners to the save and load buttons to override the default save and load behavior:
panel.savePressedE.addListener([this]{ // custom save return true; // to mark the event as attended // so the gui doesn't do the default save }); panel.loadPressedE.addListener([this]{ // custom load return true; // to mark the event as attended // so the gui doesn't do the default load });
Also specifying a ".json" file when creating a panel instead of an ".xml" will load and save from json.
The annual community survey is live! This survey helps us get information about how people are using openFrameworks, who our community is, and how we can best continue development and support.
It’s helpful to hear from everyone who’s using OF -- so if you’re a total beginner, a longtime expert, a community organizer, a programmer, a student, etc -- all opinions are appreciated! If you’ve filled out the survey in past years, we’d love for you to complete this year’s too.
The survey is published in several languages; feel free to fill out the survey in the language of your choice and the results will be aggregated together.
openFrameworks 0.9.0: ofThreadChannel, UTF-8 and ofSoundBuffer
OF 0.9.0 Overview Part 1 - Major Changes
OF 0.9.0 Overview Part 2 - OpenGL 4.5
OF 0.9.0 Overview Part 3 - Multi-window and ofMainLoop
OF 0.9.0 Overview Part 4 - ofThreadChannel and UTF-8 support
ofThreadChannel
Multi-threaded applications are more and more common given that most computers and devices have more than one CPU.
Threading is useful if we have a process-intensive task that we don't want to interfere with the main thread's task which is usually drawing at 60fps. Threading provides a way to continue drawing quickly and allowing process-intensive tasks to continue in the background. Once a background task is complete, the data or result can be accessed from the main thread.
The traditional way of communicating threads in OF has been through some kind of lock before accessing shared memory between the main thread and a thread that does some kind of auxiliary work. This can be error prone since it is really easy to forget locking in the correct places and cause application crashes or lock more than necessary and cause deadlocks that freeze the application.
OF 0.9.0 comes with a new class, ofThreadChannel, that makes inter thread communication much easier without having to explicitly use mutexes or similar. You can think of a channel as a way to send information from one thread to another. Instead of having 2 threads that try to access to the same data now we have threads that access their own data and send it as a message to each other when they are done processing the data or when there's new data to process.
Channels are thread safe so all this happens without us having to use any kind of lock in our code. Additionally the worker thread can sleep until there's new data to be processed by calling ofThreadChannel::receive which will use 0% CPU while there's no data to process and only wake up when there's something to do.
There's some examples showing how to use ofThreadChannel in examples/utils/threadChannelExample which shows some generic usage of this new class or examples/gl/threadedPixelBufferExample which shows how to download pixels from the GPU using a buffer object in a different thread. ofxThreadedImageLoader's code is also a good example of how to use ofThreadChannel to send jobs to a worker thread and get the result back in the main thread. In all this examples there's no explicit locking any more which makes multi threading programming way easier and less error prone.
The idea of a channel is inspired by similar utilities in some modern languages like
And others, all languages, with multi-threading as a central part of their design.
UTF-8 Support
As part of the removal of Poco we've introduced a minimal, header only library, utf8cpp. utf8cpp allows to iterate a string containing UTF-8. In 0.9.0 there's a new class: ofUTF8Iterator which uses this library to provide an easy way to iterate over every utf-8 codepoint in a glyph.
UTF-8 is a variable length encoding which means that in a UTF-8 string we can't do something like:
for(auto & c: str){ //do something with c }
or
for(int i=0; i<str.size(); i++){ char c = str[i]; //do something with c }
and expect c to be a correct UTF-8 codepoint since every character can be 1 byte, 2 bytes and even 4 bytes long depending to the alphabet it belongs.
ofUTF8Iterator wraps a string and allows to retrieve the correct codepoints from it like:
for(auto & c: ofUTF8Iterator(str)){ //do something with c }
This is already used by OF internally to do some string manipulations like ofToLower and in the next release will allow to add support for full UTF-8 in ofTruetypefont which already lives as a pull request waiting to be merged after 0.9.0 is released: openframeworks/openFrameworks#3992
Another useful UTF-8 function in OF 0.9.0 that complements ofUTF8Iterator is ofAppendUTF8, which allows to append a UTF8 codepoint to an std::string. For example if you get a character from the keyboard callback other than the limited latin 1 range you can't add it to a string by appending it as a character, ofAppendUTF8 allows to append any character from any alphabet by doing:
ofAppendUTF8(str,key)
ofSoundBuffer
ofSoundBuffer is part of a refactoring of the sound system that allows to simplify the callback for sound streams by passing an object instead of several parameters. It provides some basic operations over an audio buffer which make it easier to work with audio. It's supposed to be the basis for other utils and addons which work with audio in OF. You can think of ofSoundBuffer as the equivalent to ofPixels for working with audio.
OF 0.9.0 Overview Part 1 - Major Changes
OF 0.9.0 Overview Part 2 - OpenGL 4.5
OF 0.9.0 Overview Part 3 - Multi-window and ofMainLoop
OF 0.9.0 Overview Part 4 - ofThreadChannel and UTF-8 support
Multi-window support
OF 0.9.0 now natively supports several windows per application. To use more than one window, instead of the traditional main.cpp entry:
int main( ){ ofSetupOpenGL(1024,768,OF_WINDOW); ofRunApp(new ofApp()); }
You can do something like:
int main( ){ ofGLWindowSettings settings; settings.width = 600; settings.height = 600; settings.setPosition(ofVec2f(300,0)); auto mainWindow = ofCreateWindow(settings); settings.width = 300; settings.height = 300; settings.setPosition(ofVec2f(0,0)); auto guiWindow = ofCreateWindow(settings); auto mainApp = make_shared<ofApp>(); auto guiApp = make_shared<GuiApp>(); ofRunApp(guiWindow, guiApp); ofRunApp(mainWindow, mainApp); ofRunMainLoop(); }
Where ofApp is the main app as we've always had, GuiApp is a second ofBaseApp class and each of them is run on a different window with:
Once we've created both app objects and windows and told OF in which window we want each app object to run we start the main loop by calling:
ofRunMainLoop();
There's several types of window settings classes depending on the platform and the type of window we want to use, this new object allows to specify things like the position and size of the window, GL version and others depending on the type of window. Each window class has it's own settings object which specifies different settings. For example, with ofGLFWWindowSettings we can specify if the window starts as an icon, has decorations, or in which monitor it should be created.
Every call to ofCreateWindow, returns a sharedptr to a window, is recommended when using several windows, to keep the instance accessible so we can query things like width, height, position or in general any property of each window. The usual way to do was with function calls like, ofGetWidth, ofGetHeight, ofGetWindowPosition, which still work and if you use 2 applications the returned values will belong to the window to which that application was associated in main. Even with that when looking at code it can be confusing to understand which window ofGetWidth() is refering to in each call when we have more than one window. If we keep a copy of the sharedptr for each window and pass it around or have some kind of singleton in our application that allows us to access it then we can call for example mainWindow->getWidth() instead of only ofGetWidth which makes the code easier to maintain and understand later
There's more details about how to use this new features in examples/events/multiWindowExample and examples/events/multiWindowOneAppExample
ofMainLoop
ofMainLoop takes care now of holding every window in the system and of the loop logic unless the underlying system provides a loop already (like is the case with Android and iOS).
By default OF will create an ofMainLoop singleton, which is the only singleton or static variable in the whole graphics engine and holds every window which in turn hold a renderer each.
Optionally and right now only as a experimental API one can avoid completely any singleton, even the main loop, by creating explicitly one or more ofMainLoop and windows in main, each main loop can potentially even run in a different thread as long as no global calls are made. The global calls are everything in ofGraphics, of3dGraphics and every object draw and bind.
Draw calls like
ofDrawCircle(10,10,100);
would become
gl.drawCircle(10,10,100);
Where gl is a renderer usually hold by a window and drawing and binding objects would be done through that same renderer like:
There's an example of how to do this in our github repository in apps/devApps/explicitRendererExample.
These changes, although still in a experimental phase as a public API are used internally by the OF core, and prepare OF to work with the new graphics APIs to come, like Vulkan, that will substitute OpenGL in the future and which will be oriented towards multi-threaded applications.
This also allows some advanced usage of OF, for example by compiling it as a shared library and loading it multiple times from the same process without having problems that the use of singletons and static variables would cause and in general makes OF more flexible as a library.
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality
Anya is LIVE right now
FREE
Free to watch • No registration required • HD streaming
OF 0.9.0 Overview Part 1 - Major Changes
OF 0.9.0 Overview Part 2 - OpenGL 4.5
OF 0.9.0 Overview Part 3 - Multi-window and ofMainLoop
OF 0.9.0 Overview Part 4 - ofThreadChannel and UTF-8 support
With openFrameworks 0.8.0, about 2 years ago, we introduced the programmable renderer which started migrating OF from the fixed pipeline onto the newer OpenGL 3 API with support for OpenGL 3.2. With this release, we attempt to fully embrace the simpler and powerful features that became available with the latest OpenGL versions, all the way up to OpenGL 4.5.
Apart from performance optimizations and code cleanups, we have added features like on-the-fly mipmap generation to ofTexture, and for ofFbo, the ability to bind and render to multiple render targets at the same time. ofFbo now also supports MSAA filtering (a.k.a. multisampling) more robustly. Another feature is the ability to create meshes with arbitrary vertex attributes using ofVbo. This gives advanced users all the flexibility they need to get the correct in's and out's to their shaders. Speaking of ofShaders, these now will now let you know (with some code context and line numbers in the oF console) where compilation failed, if an error was detected.
We have also simplified the way you choose the OpenGL version you want to use for your app:
// main.cpp (openFrameworks 0.8.4) int main( ){ ofSetupOpenGL(1024,768,OF_WINDOW); ofRunApp(new ofApp()); } // main.cpp (openFrameworks 0.9) int main(){ ofGLWindowSettings settings; settings.setGLVersion(4,5); /// < select your GL Version here ofCreateWindow(settings); ///< create your window here ofRunApp(new ofApp()); }
The old method of creating a simple window with the default settings still works, but we've removed the old way of choosing the programmable renderer, now you just need to specify which version of OpenGL to use and OF will use the programmable renderer internally if you choose anything higher than 3.0
ofBufferObject
An example for this is how we now deal with ofVbo data internally: it's all backed by a new object, ofBufferObject, a thin wrapper around GPU held data.
An ofBufferObject is an object oriented wrapper of an OpenGL buffer and allows to reserve memory in the GPU for lots of different purposes. ofBufferObject uses the named buffers API which allows to upload data and map GPU buffers i in memory space without having to bind them to any spècific target. This API makes the usage of GL buffers much cleaner since it avoids the use of global state in most cases which is something we are aiming for in all the rendering pipeline. Although this API is only really available since OpenGL 4.5 for lower versions of OpenGL we emulate it so you don't have to deal with the different bindings of GL buffers until it's really necessary.
An ofBufferObject is in principle just memory in the GPU but depending how it's bound it can serve very different purposes. There's a few examples in the gl section that show how it can be used.
pixelBufferExample and threadedPixelBufferExample show how to use ofBufferObject as a PBO (pixel buffer object), which allows to upload or download pixels information to and from the GPU in an asynchronous manner and even in a different thread leaving the CPU free for other tasks while the data is being uploaded or downloaded. This is really useful for things like recording the screen or faster playback of videos or image sequences.
The computeShaderExample, which will only work with openGL 4.3 (so not in osx yet) shows the usage of compute shaders but also uses an ofBufferObject to pass data about a particle system from the compute shader where the positions, forces and interactions between each particle are calculated to a vbo where the same buffer is used to draw the particles. In this case the buffer is bound to 2 different targets one as a shader storage buffer (SSBO) and later as a vertex buffer object.
The textureBufferInstancedExample shows how to use a texture backed by an ofBuffer, in openGL terminology a TBO (texture buffer object) to send information about position and rotation to a shader. This is handy in lower openGL versions where SSBO are still not supported to send more data than we can usually upload in a uniform.
That's only a few examples but ofBufferObject can be used form many other things, we've tried to mantain the original OpenGL syntax as much as possible in it's methods so any OpenGL reference can be easily translated to using this object but also introduced some higher level utils that make it's usage much simpler than the original OpenGL API.
For example a buffer object can be mapped to a memory address so we can read or write data from or to the GPU memory. In the OF object we can map that memory with any type, for example if we have a vertex object we can map the buffer as ofVec3f like:
ofBufferObject buffer; // uplaod some vertices to the buffer // probably through a vbo ofVec3f * data = buffer.map<ofVec3f>(GL_WRITE_ONLY); // do something with the data, usually copy a vector // or some other data into it
Or we can wrap the mapped memory into an ofPixels which allows to use the high level operations that ofPixels provides over data in the GPU.
The core also uses internally ofBufferObject in different places, for example ofVbo is now backed by this object or all the save screen facilities in OF like ofSaveScreen or ofSaveFrame now use ofBufferObjects to make reading back from the graphics card much faster.
Shader based lights and materials on OpenGL 3+
With the introduction of the programmable renderer around 2 years ago, one of the things that we lost when using OpenGL 3 was support for lights and materials since there's no standard implementation in OpenGL 3+ and instead shaders are needed for material and lighting calculations.
OF 0.9.0 introduces some custom shaders that do phong shading per-fragment (as opposed to the per-vertex lighting you'll get with the fixed pipeline). The usage is fully compatible with previous versions, any application using ofMaterial and ofLight will keep working the same when switching to OpenGL 3+ but with better quality lighting.
There's also support for a new type of light, area lights, that allows to create a rectangular source that emits light equally in all it's area. There's an example of how to use it in examples/gl/areaLightExample
In the future we will extend materials and lighting support so they may be extended and used with custom lighting shaders.
If you want to use your own lighting shaders you can still use ofLight. When using the Programmable renderer, ofLight is a data container for the light transformation (an ofNode) and contains properties that you are able to send to your own shaders.
A new useful function for lighting calculations is ofGetCurrentNormalMatrix() which returns the current normal matrix which is usually needed to calculate lighting.
OF 0.9.0 Overview Part 1 - Major Changes
OF 0.9.0 Overview Part 2 - OpenGL 4.5
OF 0.9.0 Overview Part 3 - Multi-window and ofMainLoop
OF 0.9.0 Overview Part 4 - ofThreadChannel and UTF-8 support
This is one of the biggest openFrameworks releases to date, and will probably be one of the biggest ever as we move to a more regular release cycle.
Some stats: The previous version, 0.8.4, was released September 19, 2014, and the last major version bump 0.8.0 was released August 9, 2013. The 0.9.0 Milestone shows 190+ closed issues, 115+ closed PRs, and almost 3000 commits since the last release. Development has been lead by Arturo Castro (arturoc), with contributions from approximately 100 people.
This post dives into more of the details around the release – we’ll be doing a series of posts with different details. This one covers major changes to the core of OF as well as a list of everyone who was involved.
Major updates: C++11 support, removal of Poco
With C++11 to C++14 support for all platforms, the C++ standard library now or in the near future will provide all the core features we used from Poco. Features that are still not part of C++14 are temporarily provided via boost::filesystem. The Poco libraries still come packaged with OF to retain backwards compatibility for anybody who is using the Poco libraries directly.
openFrameworks 0.9.0 now has support for C++11 in every platform and we’ve begun to adapt the core to support several patterns that are introduced in C++11 and make the usage and syntax easier.
As an example of the integration of C++11 in openFrameworks we have now support for iterators in every collection in the core and most addons.
Iterators are not a new thing in C++ but their syntax was really cumbersome before the C++11 standard. The new standard introduces range-based for loops which makes iterators much easier to use than before. This kind of for loops avoid any indices to iterate over a collection with a syntax that is really clean and friendly.
For example this is how you would go through every line and every pixel in an image in OF 0.8.4 and before and in OF 0.9.0:
ofPixels pixels; // pre 0.9.0 for(int y=1;y<h;y++){ for(int x=0;x<w;x++){ pixels[x*3+y*w*3]; // red channel on an rgb image if(y>0){ pixels[x*3+(y-1)*w*3]; // get the pixel 1 line above this one } } } // 0.9.0 for(auto line: pixels.getLines()){ for(auto pixel: line.getPixels()){ pixel[0]; // red channel on any image if(line.getLineNum()>0){ auto pixelAbove = pixel - pixels.getWidth(); // get the pixel 1 line above this one } } }
The new version, by not using indices, makes the syntax clearer and less error prone. Also in the new version if we change for example the number of channels in the ofPixels, the for loop keeps working the same, since we are not iterating any more over bytes in an array but over pixels in an image no matter how many channels each pixel has.
A similar syntax can be used with every collection in OF now, like ofBuffer to iterate over lines in a text buffer, ofDirectory to iterate over every entry in a directory, ofxSvg to iterate over every path in an svg…
There’s more C++11 features in the core and in next releases we’ll integrate others, like for example allowing lambda functions as listeners for events which is already working as a pull request and will be merged in the core soon.
New platforms
Emscripten: Emscripten allows openFrameworks applications to be run in a web browser.
Raspberry Pi 2: The Raspberry Pi2 is now supported and set as the default variant for arm7.
64 bits: 64 bit support for Mac/Windows/iOS openFrameworks now supports 64-bit compilation on OS X, iOS, Windows (and linux which was already supported). Supporting this architecture meant removing 32-bit only QuickTime video playback and capture code, and substituting it with AVFoundation in OSX and Direct show in Windows.
openFrameworks is now compatible with the Apple Store requirements for all iOS applications to support 64bit.
Developer Notes
New Library build process via Apothecary
One of the hard parts of getting started with C++ is building libraries. One reason OF was created was to make libraries more accessible, and allow people to easily work with different kinds of media. In order to accomplish this, we precompile libraries and distribute them for all the platforms we use. But as the number of platforms has increased the number of libraries we need to compile has also increased, which means that when we want to update a library we have to carefully recompile it for all the different platforms.
To automate this process, in 2013 Dan Wilcox developed a tool called Apothecary, with the support of the Frank-Ratchye STUDIO for Creative Inquiry at CMU. Apothecary allows us to keep track of all the different repositories, build flags, and patches we make to different libraries in order to get them all building and running for different platforms. When we need to update a library to get the latest features, there’s less repetitive work, and we don’t need to track down the one person who knew how to build that library.
With 0.9.0 we’ve integrated Apothecary into the OF workflow by writing “formulas” (shell scripts) that describe how to build all the libraries that OF uses on every platform.
Continuous Integration
During the 0.9.0 release cycle we’ve stated to add some continuous integration to our workflow. Every time that there’s a new commit or someone sends a pull request the whole core is compiled in all the platforms we support except for linux arm and emscripten by now. We also test that the empty example and the all addons example keep compiling and run some tests that ensure that things keep working as they should with the new code.
By now we have tests for the filesystem classes and utilities, for ofPixels and for the string manipulation functions but we’ll keep adding more unit tests in the future.
This makes the openFrameworks core and official addons much more stable and at all times we can know that the master branch is working in all platforms or will keep working if we merge a pull request.
With time we receive more and more contributions from different people so having unit tests and knowing that everything will keep running after merging some contribution already helps making it easier to accept all the pull requests that we receive.
Community Notes
ofxaddons.com
While ofxAddons is on a different cycle than the openFrameworks codebase, some big changes have happened since the last release. Most importantly, it loads a lot faster and is much easier to navigate. All these changes were made by James Hughes (jamezilla) earlier this year.
ofBook project
The ofBook project started in early 2014, and had its first private preview in January 2015. After the release of 0.9.0 we are also working to release ofBook. It’s huge group effort lead by a few dozen people, starting with organizational efforts, brainstorming, and writing, and most recently a lot of editing.
Contributors to the ofBook project Abe Pazos, Abraham Avnisan, Adam Carlucci, Andy Clymer, Arturo Castro, Blair Neal, Brannon Dorsey, Brett Peterson, Caitlin Morris, Christoph Buchner, Christopher Baker, Daniel Rosser, Elburz Sorkhabi, Eva Schindling, Eve Weinberg, Gerben Neven, Golan Levin, Hyeongbin Kim, Ishac Bertran, Jane Friedhoff, Jason Alderman, jeffro-, Joel Gethin Lewis, Jonas Jongejan, Josh Nimoy, Joshua Nimoy, Joshua Noble, kavinhan, Kayla Lewis, Lionel Radisson, Lukasz Karluk, Marcus Russi, Matt Felsen, Matthew Hollings, Memo Akten, Michael Hadley, Mimi Son & Elliot Woods (Kimchi and Chips), Nuno Martins, Omer Shapira, Patricio Gonzalez Vivo, Phoenix Perry, Pierre Proske, Pierre Thirion, Rachel Uwa, Riccardo Canalicchio, Roy Macdonald, Rui Pereira, Serkan Sökmen, Tega Brain, Tobias Zehntner, Todd Thille, tpltnt, Zach Lieberman For the official credits see http://openframeworks.cc/ofBook/chapters/foreword.html#credits
Contributors to 0.9.0 openframeworks.cc Aaron Waterhouse, Adriano D.G., Andrew McWilliams, Antoine Villeret, Arturo Castro, Basheer Subei, Caitlin Morris, Cameron Browning, Christoph Mauerhofer, Christopher Baker, Constantine Tarasenkov, David Newbury, Davide Prati, edapx, Giuseppe Torre, Giuseppe, Hector Lee, Isaac Lemus, Jason Van Cleave, jbl0ndie, Johnty Wang, Jordan Shaw, Kyle McDonald, Lauren McCarthy, lilive, Nick Devereaux, Peter Dave Hello, Sarah Howorka, Theo Watson, Tobias Zehntner, tpltnt, Zach Lieberman
Contributors to 0.9.0 code base Aaron Freedman, Abhi, Adam Carlucci, AmnonOwed, Andreas Müller, Andy Duplain, Arthur Carabott, Arturo Castro, Bo Brinkman, Cameron Browning, Carsten Schwede, Charles Veasey, Christoph Buchner, Christoph Mauerhofer, Christopher Baker, Constantine Tarasenkov, Daan de Lange, Damian Stewart, Damien Lespiau, Dan Moore, Dan Wilcox, Daniel Rosser, Darío Hereñú, dmytroshp, Dominic Amato, elaye, Elie Zananiri, Elliot Woods, eranws, Felix Dubrownik, Felix Lange, Gal Sasson, Gorka Cortazar, Graham Reeves, Grégory DAVID, hardmanko, Hubris, Ingo Randolf, ISHII 2bit, Jakob Schindegger, jamet, Jason Knight, Jason Van Cleave, Jean-Pierre Mouilleseaux, Johan Bichel Lindegaard, Jonas Jongejan, Jonathan Dahan, Joshua Noble, Julian Adenauer, kentaroid, Kevin Pouget, Kojo Kumah, Kyle McDonald, Lennart Melzer, Liam Staskawicz, Lorenzo Mancini, Lukasz Karluk, László Kustra, Léo Colombaro, manish-juneja, Marcel Ruegenberg, Mark Hintz, Matt Felsen, Mattijs Kneppers, Memo Akten, Michael Hadley, Michael Hansen, Nick Hardeman, noyanc, nykwil, Patrick Fürst, Pelayo Méndez, Petros Kataras, Philip Whitfield, Piotr Tarasewicz, random, rezaali, Riccardo Canalicchio, Robert Xiao, Sam Taylor, Sergio Basurco, skimon, Stefano, Sterling Crispin, Tal Lavi, Theo Watson, Thomas Geissl, Tim Gfrerer, Timon Skerutsch, Timothy Scaffidi, Tom Butterworth, tpltnt, Trent Brooks, Tristan Fisher, Valentino Dell'Aica, Vincent Donnefort, wronex, Zach Lieberman
At the end of 2014, we released our second community survey, asking for input from anyone working with openFrameworks, at any level of experience and involvement. Thanks to the help of a number of translators, we were able to release this year's survey in five languages (English, Japanese, Spanish, Chinese, and Russian). We're excited to have received 570+ responses across the languages, and are grateful for the thoughtful and thorough responses which enable us to continue working towards strengthening openFrameworks as both a tool and a community.
The survey was a mix of long-form responses and binary / multiple-choice questions. The results of the non-long-form questions (and a few long-form questions, condensed!) are shown below; these graphs represent a merged total across all languages unless noted otherwise.
[Note: though the survey was conducted in multiple languages, this analysis is currently being written only in English! If you'd like to translate this post or help with the translation of the long-form questions, please get in touch by email or twitter.]
-- -- --
DEMOGRAPHICS
-- -- --
English was the dominant language of response in the survey; however 170+ respondents answered to the non-English-language surveys.
In fact, 36 primary languages were represented across the respondents of the survey. Shown here are languages with more than 10 respondents:
An even greater number of languages was indicated as the primary language of between 1 and 10 community members.
1 to 5 community members use as their primary language: Alsacian, Arabic, Bulgarian, Cantonese, Danish, Finnish, Hebrew, Hindi, Hungarian, Indonesian, Norwegian, Polish, Romanian, Shqip, Slovak, Tamil, Thai, Urdu, or Vietnamese.
5 to 10 community members speak Greek, Korean, Russian, Swedish, or Turkish as their primary language.
This diversity is also reflected in the home / working location of community members worldwide.
(More detailed view of Europe / North Africa)
The community respondents identified predominantly as male (nearly 95%), with female and non-binary gender identities a distinct minority.
Among the respondents, the greatest distribution was in the 26-35 year range, with a handful of responses in the >60 and <18 range.
Interestingly, a disproportionately large number of the respondents in the 18-21 year range answered to the Japanese language survey or indicated Japanese as a primary language; over 15 percent of Japanese respondents are in the youngest age category as compared to about 2 percent in other languages.
Asking community members to label themselves by multiple choice (though understandably a challenge!) reveals a wide range of identities across developers, artists, and other professions. Common write-in answers include interaction designers, game developers, and engineers.
-- -- --
OPENFRAMEWORKS USE AND EXPERIENCE
-- -- --
The survey responses indicate a balanced range of experience in openFrameworks consistent with last year's survey. The slight bias towards more experienced users seems to reflect -- as also corroborated through anecdotal evidence -- that a lot of beginners or students don't feel that they're qualified to take the survey. (Note for the future: beginner feedback is equally important; everyone is qualified!)
Interactives and graphics programming are the most common uses for OF, followed closely by computer vision. Game development, while not originally a multiple choice option, was a significant write-in answer.
The majority of the openFrameworks community has not learned OF in any formal academic program.
However, a relatively large percentage of the community is either teaching OF in school or has taught at workshops.
One of the most interesting results of this question (have you taught OF?) was that a significant number of people, at least 60 respondents, mentioned that although they haven't taught OF in a classroom or workshop setting, they teach "at lunch to colleagues" or "in [their] dorm room to friends" or "to [their] children". This reveals a wonderful and personal networked means of sharing OF outside of traditional academic communities, and we'd like to continue encouraging and supporting this form of community development as much as possible.
Among the survey respondents, a majority indicate that they use openFrameworks for some portion of their income-generating work:
-- -- --
OPERATING SYSTEMS / DEVELOPMENT ENVIRONMENTS
-- -- --
Across the total sum of languages, MacOSX remains the most commonly used operating system. Raspberry Pi and various mobile platforms show a significant increase in use since last year's survey.
Each survey language reveals slightly different trends in operating system preference; OS percentage by language is shown below.
For OF users on OSX, XCode is the dominant IDE to near exclusivity.
Windows users show a slight preference for Visual Studio over Code::Blocks:
Linux users responded with a much wider range of preferred development tools.
-- -- --
OPENFRAMEWORKS RESOURCES
-- -- --
Most of the community indicates that they've been able to successfully work with addons, though a large number indicate either struggle or complete inability to work with an addon.
Based on multiple choice response, the most common use of the documentation is as a syntax reference, with a large section of users also aiming to use the documentation as a resource to find unknown functions.
The forum is the leading place for OF users to look for help with questions, closely followed by other online resources like StackOverflow. Posting questions on Twitter was another common write-in answer, especially among the Japanese-language community.
The survey included a number of long-form response questions about peoples' challenges and successes using and learning openFrameworks. These longer answers individually are helpful in determining what steps might be most helpful moving forward. Here, these answers are distilled into word clouds for easier parsing. Note: these word clouds only take into account the English language responses to the survey (again, any interest in translating or providing similar processing of the non-English results is absolutely welcome!).
"What is your ideal reference page?"
Many people indicated that having examples on a reference page would be helpful, pointing to sites like processing.org and some of the existing openFrameworks documentation that contains simple examples alongside the syntax documentation.
"What is the worst thing about using OF?"
Many people here point to the documentation as incomplete or sometimes difficult to use. This is a work in progress and individual feedback on suggested improvements to the documentation are helpful as we continue to work on it! A number of survey respondents also indicated that they'd be interested in contributing in some way to development, and documentation is a great place for people to jump in, as sometimes beginners can be even better at making comprehensive documentation than advanced users.
"What is/was the most challenging part of learning OF?"
Challenges with C++ in general and specific IDEs (such as XCode) make up the majority of responses about learning challenges, as well as the previously mentioned gaps in documentation.
"What is/was the most helpful thing for learning OF?"
Community members point to the packaged examples as a hugely helpful resource while learning, and a number of people also called out the "Getting Started" tutorials on the documentation site as a helpful starting place.
"What is the best thing about OF?"
We're happy that, in addition to the toolkit being "powerful / easy / fast", many people list the community around openFrameworks as one of their favorite things about it.
-- -- --
THANK YOU / 谢谢 / ありがとう / спасибо / GRACIAS
-- -- --
Many thanks to everyone who took the time to provide this information for us! We're grateful that you're working with us to keep building this tool and community.
We'll be in touch with a bunch of you who've indicated interest in getting involved, either through making documentation, coming to meetups, being involved through Google School of Code, and other means. For anyone who's interested in helping out or getting involved in any way, please get in touch! You can reach us on Twitter @openframeworks or by joining the of-dev list and following information about development and documentation needs.
Thanks - we're looking forward to getting to know you more!
Every so often, we like to get some information from you that helps us learn more about what openFrameworks is used for, who's using it, and how we can continue developing and making things simpler, friendlier, and more robust to use. The results from last year's survey were really insightful, and the community grows and changes every year, so we'd love to get your input again and continue to learn.
If you're about to download openFrameworks for the first time -- if you've been using it for a decade -- if you don't write code yourself but you're interested in it, or work with people who do -- we want your responses!
This year, we're publishing the survey in several languages to better reflect our community demographics. Feel free to take the survey in your preferred language (or let us know in the comments of the survey if there's another language we should be including!):
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality
Anya is LIVE right now
FREE
Free to watch • No registration required • HD streaming
Google Summer of Code is a program that offers student developers $5000 stipends and mentorship to write code for various open source projects. openFrameworks is participating in GSOC 2014 under the umbrella of the Processing Foundation. We are looking for students interested in working on ofxaddons.com, the OF project generator, an OF testing framework, or other ideas you come up with!
If you are interested in participating, learn more by reading the GSOC FAQ and OF Ideas List, then submit your application via the Processing Foundation. Be sure to include ATTN: OPENFRAMEWORKS in your application so we know it is an OF application.
Note that undergrad, grad, and phd students are eligible, as well as students graduating in May. See information on eligibility here. The deadline is Friday, March 21 at 19:00 UTC.
We are working on getting the 0.8.1 release out the door.
As part of that we put out a Release Candidate for public testing.
It would be great if people could download the zips for the platforms they use and see if they notice any issues.
What would also be really helpful, is if you could try running existing projects with 0.8.1 RC1 to see if issues arise. That seems to be a really good way to find potential bugs / regressions.
Here is a issue tracking problems with the example projects:
https://github.com/openframeworks/openFrameworks/issues/2841
And another issue for problems with the release packages:
https://github.com/openframeworks/openFrameworks/issues/2849
Please reply to both with issues you notice from the RC1 zips.