In this chapter we will deal with 2D graphics. 2D graphics can be created in the following ways:
openFrameworks has the following functions for drawing primitives:
ofLine( x1, y1, x2, y2 )
: This function draws a line segment connecting points (x1
, y1
) and (x2
, y2
)ofRect( x, y, w, h )
: This function draws a rectangle with the top-left corner (x
, y
), width w
, and height h
ofTriangle( x1, y1, x2, y2, x3, y3 )
: This function draws a triangle with vertices (x1
, y1
), (x2
, y2
), and (x3
, y3
)ofCircle( x, y, r )
: This function draws a circle with center (x
, y
) and radius r
openFrameworks has no special function for changing the color of a separate pixel. To do so, you can draw the pixel (x, y) as a rectangle with width and height equal to 1
pixel; that is, ofRect( x, y, 1, 1 )
. This is a very slow method, but we sometimes use it for educational and debugging purposes.
All the coordinates in these functions are float
type. Although the coordinates (x, y) of a particular pixel on the screen are integer values, openFrameworks uses float numbers for drawing geometric primitives. This is because a video card can draw objects with the float
coordinates using modeling, as if the line goes between pixels. So the resultant picture of drawing with float coordinates is smoother than with integer coordinates.
Using these functions, it is possible to create simple drawings.
Let's consider the example that draws a circle, line, and two triangles, which forms the simplest kind of flower.
This example project is based on the openFrameworks emptyExample
project. Fill the body of the testApp::draw()
function with the following code:
ofBackground( 255, 255, 255 ); //Set white background ofSetColor( 0, 0, 0 ); //Set black color ofCircle( 300, 100, 40 ); //Blossom ofLine( 300, 100, 300, 400 ); //Stem ofTriangle( 300, 270, 300, 300, 200, 220 ); //Left leaf ofTriangle( 300, 270, 300, 300, 400, 220 ); //Right leaf
On running this code, you will see the following picture of the "flower":
There are a number of functions for controlling the parameters for drawing primitives.
ofSetColor( r, g, b )
: This function sets the color of drawing primitives, where r
, g
, and b
are integer values corresponding to red, green, and blue components of the color in the range 0
to 255
. After calling ofSetColor()
, all the primitives will be drawn using this color until another ofSetColor()
calling. We will discuss colors in more detail in the Colors section.ofFill()
and ofNoFill()
: These functions enable and disable filling shapes like circles, rectangles, and triangles. After calling ofFill()
or ofNoFill()
, all the primitives will be drawn filled or unfilled until the next function is called. By default, the shapes are rendered filled with color. Add the line ofNoFill();
before ofCircle(...);
in the previous example and you will see all the shapes unfilled, as follows:ofSetLineWidth( lineWidth )
: This function sets the width of the rendered lines to the lineWidth
value, which has type float. The default value is 1.0
, and calling this function with larger values will result in thick lines. It only affects drawing unfilled shapes. The line thickness is changed up to some limit depending on the video card. Normally, this limit is not less than 8.0.Note that this method for obtaining thick lines is simple but not perfect, because adjacent lines are drawn quite crudely. For obtaining smooth thick lines, you should draw these as filled shapes.
ofSetCircleResolution( res )
: This function sets the circle resolution; that is, the number of line segments used for drawing circles to res
. The default value is 20
, but with such settings only small circles look good. For bigger circles, it is recommended to increase the circle resolution; for example, to 40
or 60
. Add the line ofSetCircleResolution( 40 );
before ofCircle(...);
in the previous example and you will see a smoother circle. Note that a large res
value can decrease the performance of the project, so if you need to draw many small circles, consider using smaller res
values.ofEnableSmoothing()
and ofDisableSmoothing()
: These functions enable and disable line smoothing. Such settings can be controlled by your video card. In our example, calling these functions will not have any effect.Performance considerations
The functions discussed work well for drawings containing not more than a 1000 primitives. When you draw more primitives, the project's performance can decrease (it depends on your video card). The reason is that each command such as ofSetColor()
or ofLine()
is sent to drawing separately, which takes time. So, for drawing 10,000, 100,000, or even 1 million primitives, you should use advanced methods, which draw many primitives at once. In openFrameworks, you can use the ofMesh
and ofVboMesh
classes for this (for details, see the Using ofMesh section in Chapter 7, Drawing in 3D).