In the previous tutorial, we saw how to draw OpenGL graphics into a jit.window using the jit.gl.render object. Now we will look at the other kinds of destinations into which a jit.gl.render object can draw, what to use them for, and how to switch between destinations.

In the upper left of the patch is a jit.gl.render object with an argument of inky, along with other objects.

• Click on the toggle in the upper left of the patch labeled Start Rendering.

You should see a red ball appear in the jit.window object. The jit.gl.gridshape object is drawing the ball. Its first argument, inky, specifies the drawing context currently being drawn by the jit.gl.render object to the jit.window. The other arguments set the color and scale attributes of the ball.

Draw a red ball in the window named inky

Drawing and Swapping Buffers

Clicking the toggle starts the qmetro object, which sends bang messages to the object tb b erase. This object first sends an erase message followed by a bang message to the jit.gl.render object, and then a bang message that is used elsewhere in the patch.

When the jit.gl.render object receives the bang message, it draws all of the GL group objects which share its destination, then copies its offscreen buffer, if any, to the screen. An offscreen buffer is an area of memory not visible on the screen, the same size as the drawing destination. By default, all drawing contexts have an offscreen buffer. Drawing is done into the buffer, which must then be copied to the screen in order to be seen.

The offscreen buffer makes flicker-free drawing and animation possible, as we see here. Even though the buffer is being erased before the red ball is drawn each time, we never see the buffer in its erased state. To see what drawing looks like without the offscreen buffer, click on the message box doublebuffer 0 in the upper right of the patch . You will probably see the image start to flicker. This happens because the erase message now causes the window itself to be erased, not the offscreen buffer. The window remains blank for a short but indeterminate period of time before the red ball is drawn, so you can see the area under the ball flickering between red and the dark gray of the erased window. Click the message box doublebuffer 1 to remake the offscreen buffer and stop the flickering.

Setting Fullscreen Mode

The pfullscreen subpatch contains a key object, a select object, a toggle, a message box and an
outlet object that sends the results of the subpatch to the jit.window object. This is standard
Max stuff, so we won’t go over it in too much detail— the result is that the escape key
toggles between sending the messages fullscreen 0 and fullscreen 1 to the jit.window object. (See
the "Full Screen Display" section of Tutorial 14.)

• Press the 'esc' key to change the jit.window object to fullscreen mode and back.

The escape key seems to be a common way to toggle fullscreen mode, so we’ve used this setup in many of the example patches. It’s important to note, however, that this is just a convention—there’s nothing built into Jitter that forces you to use one key or another for this purpose.

You can use the fsmenubar message in conjunction with the fullscreen message to hide the menubar in addition to covering the screen.

This names the jit.pwindow object, which allows it to be used as a rendering destination.
To switch the drawing to this destination, we need to send messages to both the
jit.gl.render object and the jit.gl.gridshape object, telling them about the new destination.

• Click on the message box blinky in the Switch Destinations section of the patch.

The symbol drawto is prepended to the message blinky, and the result is sent to the sdest
object. Two objects receive this message — jit.gl.gridshape and tl b erase. The trigger object
sends a sequence of messages to the jit.gl.render object, which tell it to:
1. Erase its current destination’s draw buffer
2. Swap that buffer to the screen, visibly clearing the old destination, and
3. Switch future drawing to the new destination.
The result is that the red ball is displayed on the jit.pwindow object at the right of the patch.

In addition to drawing to jit.window objects and jit.pwindow objects, we can draw to jit.matrix objects. We introduced offscreen buffers in the discussion of jit.window destinations, above. When a 2D jit.matrix object is a rendering destination, the jit.matrix data is used as the offscreen buffer. This puts an image of an OpenGL scene into the same format as video data, so that any of Jitter’s video-processing effects can be applied to the image.

The jit.matrix object must meet a few criteria in order for OpenGL graphics to be drawn into it:

• It has to have four planes of char data.

• It has to have two dimensions.

• It has to be bigger than eight pixels in both width and height.

We have such a matrix in the bottom right corner of the tutorial patch. It is 160 pixels wide by 90 pixels high—the same dimensions as the jit.pwindow object below it.

• Click on the message box clyde in the Switch Destinations section of the patch to draw into the jit.matrix object.

You should see a cyan ball on a light gray background. This is because the red ball image generated by OpenGL is processed through the jit.op object, which subtracts each color component from 255, inverting the image.

There’s one more important detail about drawing to jit.matrix objects. Note that underneath the qmetro object there’s a trigger object tb b erase. The leftmost (and therefore last) bang message from this object is sent to the jit.matrix object into which we are drawing. This is necessary to see the image in the jit.pwindow. When the jit.gl.render object receives a bang message, it finishes constructing the drawing in the offscreen buffer belonging to the jit.matrix object. But to send the resultant matrix out for viewing or further processing, it’s necessary to send a bang message to the jit.matrix object.

Hardware vs. Software Rendering: One of the great advantages about using OpenGL for rendering graphics is that most of the work can be done by the graphics accelerator hardware in your computer, freeing the CPU up for other work such as generating audio. When drawing into jit.window objects or jit.pwindow objects, the hardware renderer can be used. Unfortunately, due to limitations of the current system software (Mac OS 9) the hardware renderer cannot draw directly into jit.matrix objects. This is not a limitation inherent in OpenGL, and may change in the future. Now, however, this means that drawing directly into Jitter matrices is significantly slower than drawing to jit.window or jit.pwindow objects, especially for complex scenes or those involving textures.

Multiple Renderers and Drawing Order

To move an OpenGL scene to a different destination, the jit.gl.render object as well as any GL group objects involved in drawing the scene must receive the drawto message. Why not just send a message to the renderer, telling it to move the entire scene? The reason is that each GL group object can have an independent destination, as well as each renderer. Objects in the GL group can be moved between multiple renderers. To see an example of why this might be useful, please look at the right-hand portion of the patch for this tutorial.

At the right are three jit.pwindow objects named A, B and C. The message box objects above them are not strictly necessary, because once a jit.pwindow object has been named, its name is stored with it in the patch. But they are useful here as labels and as a reminder of what messages to send to name the objects.

There are also three jit.gl.render objects in the patch. Each of them is pointed at a different destination.

This repeatedly sends the erase message followed by a bang message to each of the three renderers. You should see a yellow circle within a blue circle in the topmost drawing destination. This simple OpenGL scene is created by the two jit.gl.gridshape objects in the bottom left of the patch. We can move each of these objects to any of the three drawing destinations present.

• Click the topmost message boxreadingBin theSwitch Destinations section of the tutorial patch. This changes the destination of the blue circle to the draw context named "B"—it now appears on the center jit.pwindow.

• Click the lower message boxreadingBin theSwitch Destinationssection of the tutorial patch. This changes the destination of the yellow circle to the draw context named "B". The two objects are reunited.

Each time a jit.gl.render object receives a bang message, it draws all of the GL group objects that have been added to its context. It draws the objects in the order in which they were added to the context. In this case, the yellow circle was added to the draw context named "B" after the blue circle, so it appears on top. To change this order, we can send the message drawto B to the jit.gl.gridshape object drawing the blue circle again. This will remove it from its present place in the list of objects for the context named B, and add it again at the end of the list.

• Click the upper message boxreadingBin theSwitch Destinationssection of the tutorial patch again. The blue circle should now obscure the yellow circle.

The blue circle obscures the yellow one

Summary

We have introduced a flexible system for creating multiple OpenGL renderers and drawing destinations, and for moving objects in the GL group between them using drawto messages.

Three Jitter objects can function as drawing destinations: jit.window, jit.pwindow, and jit.matrix. Each kind of destination has different uses. A jit.window object can be moved to different monitors and quickly enlarged to cover the screen. A jit.pwindow object keeps its location in the patch. A jit.matrix object may be used as an offscreen buffer for rendering. The output of the jit.matrix object is a rasterized image of the 3D scene, to which further video processing may be applied.