Tutorial 1c : Basic drawing functions
 
Introduction

Glide offers many possibilities for the way we can draw images, such as dots, lines and polygons. However, these functions are not directly supported by a Voodoo card, and are provided purely for the programmer's convenience. The only shape that a Voodoo card knows how to draw is a triangle. When we tell Glide to draw any shape other than a triangle, it will be internally converted to a series of one or more triangles which will then be rendered by the Voodoo card.

When you imagine drawing a shape on the screen, you probably think of it having two properties - dimension and colour. For example, you would think of a red square as being a four-sided polygon made from red pixels. The Voodoo rendering system doesn't work that way. Shape and colour are treated as two independent properties.

There are four steps involved in telling Glide to draw a basic shape:

  • Specify the shape's vertices.
  • Specify a constant colour.
  • Tell Glide to use the constant colour when drawing.
  • Draw the shape.
As you can see, instead of defining a coloured shape, we define a shape and a colour separately and then tell Glide to use the specified colour when drawing. If we then wanted to draw a different shape in the same colour, all we would have to do is define the new shape and draw it - Glide would still use the same colour. Likewise, if we wanted to draw the same shape again but change the colour, we would just specify a new colour and then redraw the shape.

Specify the shape's dimensions

As you might expect, a shape is defined using a series of vertices. We use the GrVertex structure, which holds a lot of information that we use to define a vertex, but at the moment all we're interested in are the x and y elements.

To create a vertex at position (100, 200) the code would be:

  GrVertex vertex;
  
  vertex.x = 100.0f;
  vertex.y = 200.0f;
Note: vertex positions must be specified as floating point values.

Specify a constant colour

Glide can take its colour information from numerous sources, but for the purposes of this example we're going to use the constant colour. The constant colour is a 32-bit GrColor_t value consisting of red, green, blue and alpha components, with each value being in the range 0 - 255.

Remember in the previous example how we specified that our rendering window should use the GR_COLORFORMAT_ARGB colour format? This is now relevant, because we must be sure to specify the four values in the correct order.

To specify the constant colour, we use the grConstantColorValue function, passing a GrColor_t value as the only parameter. Because GrColor_t is a 32-bit value consisting of one 8-bit value for each of the four colour components, it could be quite time-consuming and inconvenient to calculate the correct value each time we want to specify a new constant colour. To make it easy for us, we'll write a simple function that does the hard work:

  GrColor_t colour_ARGB( BYTE a, BYTE r, BYTE g, BYTE b )
  {
    return (GrColor_t) MAKEWORD( b, g ) | ( MAKEWORD( r, a ) << 16 );
  }
Note: another advantage of using a function to do this is that we could easily write a new function if we changed the colour format of our rendering window, and the rest of our code could remain unchanged.

Having decided what red, green and blue values to use, we can set the constant colour. At this stage it doesn't matter what alpha value we use, so we'll set it to zero. We'll set the constant colour to white, which means that the red, green and blue components should all be set to 255. One way to do this would be:

  GrColor_t colour;
  colour = colour_ARGB( 0, 255, 255, 255 );
  grConstantColorValue( colour );
However, you will probably want to write it more compactly:

  grConstantColorValue( colour_ARGB( 0, 255, 255, 255 ) );
Tell Glide to use the constant colour when drawing

Glide can use colours from many different sources. Think of the colour sources as a series of paint taps that we can open and close to mix the colour we want. Each tap can be fully open, fully closed or anywhere in between. For this example, all we're interested in is the constant colour value, so we want to fully open that tap and leave all of the others closed.

The function we use is grColorCombine, which takes five parameters. This function tells Glide which colours to use and how they should be mixed.

Note: don't worry too much at this stage about how this function works. We're using it at its most basic level to specify that Glide should use the constant colour and ignore all others. In future tutorials, when we'll be using more advanced colour management, the importance of this function will be a lot easier to understand.

The first parameter is the combine function. This dictates which colour sources should be used and how they should be combined. The combination factor and two possible colour sources (referred to as local and other) are specified in the next three parameters.

To tell Glide that we want to use the unmodified constant colour, the function would be called as follows:

  grColorCombine(
    GR_COMBINE_FUNCTION_LOCAL,
    GR_COMBINE_FACTOR_NONE,
    GR_COMBINE_LOCAL_CONSTANT,
    GR_COMBINE_OTHER_NONE,
    FXFALSE );
The first parameter, GR_COMBINE_FUNCTION_LOCAL, means two things: we're only interested in the local colour value (the third parameter) and we don't want to modify it in any way.

Because we don't want to modify the colour, we don't need to specify a factor in the second parameter, so we set it to GR_COMBINE_FACTOR_NONE.

The third parameter specifies which colour should be treated as local. We want to use the constant colour so we specify GR_COMBINE_LOCAL_CONSTANT. We're not using any other colours so we specify GR_COMBINE_OTHER_NONE for other, the fourth parameter.

The fifth parameter gives us the option to invert the computed colour. If this is set, the local and other colours are both combined using the given function and factor, and then the result is inverted to give the final colour. We don't want to use this option, so we set it to FXFALSE (which is just Glide's own version of the normal FALSE alias).

We can think of Glide's colour system in terms of a flowchart. Thinking of it that way, if we set the constant colour to white and put it through the system we've just created, it would work like this:

"grColorCombine" flow chart

As you can see, we have two possible input colours (local and other), but we only use one of them - the constant colour, white. After it has been combined with the other colour (which is non-existent) the result is still white, and it remains unmodified.

Draw the shape

Having defined the correct number of vertices and told Glide what colour information to use for rendering, we call the function for the shape we want to draw, with the parameters being a series of pointers to the vertices. For instance, if we wanted to draw a line, the function would be grDrawLine with two pointers to vertices passed as parameters, thus:

  grDrawLine( &v1, &v2 );
Similarly, if we wanted to draw a triangle, the function would be grDrawTriangle with three pointers to vertices:
  grDrawTriangle( &v1, &v2, &v3 );
Note: an exception to this format is when you want to draw a non-triangular polygon, ie: any shape with more than three vertices. At this stage, we are not concerned with polygons, but they will be discussed in the next tutorial.

Working example


Figure 5 : Basic drawing functions.
Download the tutor_1c example code to see a working example that will draw some green dots, blue lines and a red triangle, as shown in Figure 5.

Notice how the program is structured:

  1. Three new functions have been added - draw_dots, draw_lines and draw_triangle.

  2. After the grSstWinOpen function, we call grColorCombine as described earlier. At that stage, we haven't set the constant colour.

  3. Instead, we call grConstantColorValue once in each of the three drawing functions. It doesn't matter when we specify the colour, as long as we do it before drawing. Also notice how we change the colour three times, but we only call grColorCombine once.


Figure 6 : The FileView panel.

To compile the program, you first need to remove the example code from the previous tutorial. To do this, find the file "tutor_1b.c" in the FileView panel, as shown in Figure 6, and delete it.

Then use the InsertFile menu option to insert the new one, which you compile and run as usual.

Next Tutorial | Main Page
 


This tutorial is ©1998 by Andrew Smith. No part of this tutorial may be reproduced without permission. If you want to reproduce any of this tutorial for non-commercial purposes then I'm not likely to try and stop you, but please ask me first.