Graphics in Cinder
Cinder exposes a number of different graphics API's, each with different purposes. This guide serves as a starting point for these various technologies.
- OpenGL - Cinder's most commonly used graphics API, used for high-performance, GPU-accelerated graphics. See OpenGL in Cinder.
- Raster Images - for CPU-based image processing and I/O. Most commonly used through ci::Surface, ci::Channel and the ci::ip namespace.
- Cairo - most suitable for vector graphics (such as SVG rendering). Primarily CPU-based.
GPU vs. Raster vs. Vector
Many tasks can be accomplished with any of these API's. However they each have different strengths with respect to performance and simplicity. We'll attempt a summary below of what can be a complex topic in practice.
OpenGL (and similar technologies) are primarily based on rendering triangles, applying a shader to each pixel of a triangle. This is performed on the specialized hardware of the GPU, rather than the CPU your C++ application code runs on. To make use of either geometric or image data, we must incur a performance cost to upload this data from the CPU to the GPU. Furthermore, OpenGL does not make it simple to manipulate pixels directly in general. Additionally, triangle rasterization is not ideal for curved shapes, as it requires many triangles to create the illusion of curvature. However, GPUs often make all these costs worth our while, in both the 2D and 3D cases. The ability to render triangles extremely quickly is what makes just about all modern realtime graphics possible.
Raster (or pixel-based) graphics excel in manipulating pixels, either individually or through broad-strokes operations like blurs. It's straightforward to write C++ code that manipulates pixels in this manner. However these operations can be substantially slower than the GPU equivalents. Additionally, rendering either 2D or 3D shapes with these APIs can be prohibitively complex. In Cinder, this API is expressed primarily through the Surface and Channel classes, as well as the image processing operations in the ci::ip namespace.
Vector graphics express primarily 2D shapes as combinations of lines and Bézier curves. They're most commonly associated with print, but are useful in any context in which resolution-independence is important. Cinder provides a wrapper around Cairo - an industry-standard graphics library specifically designed for vector graphics. In order to be useful, these mathematical descriptions of shapes must be converted to pixels (rasterized), which Cairo is designed to do. Users used to the performance of hardware-accelerated OpenGL are often surprised at how much more costly CPU-based rasterization often is. As an aside, it is also possible to output these vector-based scenes using formats like PDF or SVG using Cairo. Cinder provides classes relevant for manipulating vector shapes, namely ci::Shape2d, ci::Path2d and ci::PolyLineT. Cinder also provides an SVG parser that works independently of Cairo.
It's often desirable to combine these APIs as well. Briefly, both ci::Surface and ci::Channel can be used to create images for OpenGL (called textures). Cairo can also rasterize images to ci::Surface, which can optionally be used to create an OpenGL texture. Finally, a ci::Surface can be used in various Cairo contexts such as the creation of a cairo::Pattern.