## 12.4 Setting the Display Mode

Most of the graphics state attributes can be set via the command `EZ_Enable` (see next section). However, there are two important attributes that must be set via separate function calls. These two attributes are ColorMode and BackBufferType.

### 12.4.1 Choosing a Color Mode

The EZ graphics library supports both RGB mode and Colormap (index) mode. The color mode is binded to 3DCanvases, i.e., each 3DCanvas may choose either of the two color modes. But realistically, the two color modes cannot be used simultaneously on PseudoColor displays since EZwgl uses a single physical colormap.

`void EZ_RGBMode(void);`

This function sets the display mode to RGB mode. On 8bit displays, EZwgl uses dithering to simulate a 24 bit RGB Mode.

In RGB mode, colors are referenced directly from their RGB intensities. There are two pairs of functions for setting the current color in RGB mode.

`void EZ_Color3f(float r, float g, float b)`

`void EZ_Color3fv(float rgb[3])`

`void EZ_Color3i(int r, int g, int b)`

`void EZ_Color3iv(int rgb[3])`

All these routines set the current RGB color. In the ``f`' version, RGB intensities are in the range [0.0, 1.0] while in the ``i`' version, intensities are in the range [0, 255].

`void EZ_ColorMapMode(void)`

This function sets the display mode to index mode. Care must be taken in index mode since we only have a very limited number (less than 256) of colors.

In ColorMap mode, colors are refered through a lookup table (internal color map). Entries of this table can be set/modified by calling the function

EZwgl keeps a global shared colormap of size 256. This colormap is shared by all widgets. On PseudoColor/GrayScale displays, it is not even guaranteed that one can allocate all 256 colors.

`void EZ_MapColor(int idx, int r, int g, int b);`

To set the current color in ColorMap mode, use

`void EZ_Index(int idx);`

`void EZ_Indexf(float fidx)`

### 12.4.2 Choosing a Back Buffer

Be default, the library is in single buffer mode. Whatever you draw is displayed immediately on the screen. If you want to do some animations, single buffer will not be adequate because you'll see the screen clear as well as all the drawing. During animation, you'll see a visible flickering. For such situation, it is preferable to draw a frame in a hidden back buffer and copy the completed buffer to the display (the front buffer) when done.

Buffering is controled by three items: A back buffer, an attribute to signal which buffer to draw into, and a command to copy the back buffer to the front buffer.

The following routines select a back buffer.

`void EZ_SetBackBuffer(int type);`

This function chooses a back buffer for the current graphics context. EZwgl supports two types of back buffers, an `EZ_PIXMAP` back buffer and an `EZ_XIMAGE` back buffer. The latter is usually faster on localhost. On a remote host, however, the former is usually faster since it needs less data transfer via the network.

The `EZ_XIMAGE` backbuffer does not support the standard X11 bitmap fonts and logical pixle operations. The default back buffer is `EZ_PIXMAP`.

EZwgl also provides a function to select the back buffer automatically.

`void EZ_AutoSelectBackBuffer(void);`

This function selects a back buffer based on the environment variable `EZ_BACK_BUFFER`, which can be either `pixmap` or `ximage`. If this environment variable is not set, then it makes a selection based on the following creterion: if the server supports shared memory extension and it is usable, then it selects the `EZ_XIMAGE` back buffer; otherwise, it selects the `EZ_PIXMAP` back buffer.

To signal which buffer to draw, use

`void EZ_DrawBuffer(int buf);`

Use the next function to copy the contents of a back buffer to the front.

`void EZ_SwapBuffers(void);`

### 12.4.3 Choosing a Shading Model

By default, the graphics library uses a flat shading model for coloring geometric objects, i.e., all vertices are assigned the same color. A primitive can also be smooth (Gouraud) shaded. In this model, all vertices are treated individually. The library uses linear interpolation to color the primitive. Shading model is controled by

`void EZ_ShadeModel(ind mode);`

This function selects one of the two shading modes: `EZ_SMOOTH` or `EZ_FLAT`.

### 12.4.4 Clear Color

For each 3DCanvas, there is a clear color. It is used by `EZ_Clear` to reset the draw buffer. The next two commands set the clear color.

`void EZ_ClearColorf(float r, float g, float b);`

`void EZ_ClearIndex(ind idx)`

The next command clears the specified buffers.

`void EZ_Clear(ind mode)`

Valid modes are `EZ_COLOR_BUFFER_BIT` or `EZ_DEPTH_BUFFER_BIT` or the two or'ed together.

### 12.4.5 Example G2, The Sine Curve

This short example demonstrates the use of double buffers. We create a 3DCanvas and draw a sine curve into it continuously. At each draw we shift the phase a little bit, creating the illusion of a moving wave.

We use a check button to turn the double buffer on/off. In double buffer mode, the animation looks smooth, while in single buffer mode, the curve flickers too much.

We also provide a slider to adjust the speed of the animation.

    /*************** Example G2 ******************************************/
    #include "EZ.h"

    static void eventHandler(EZ_Widget *, void *, int, XEvent *);
    static void draw(EZ_Widget *);
    static void sliderCallBack(EZ_Widget *, void *);
    static void cbtnCallBack(EZ_Widget *, void *);
    static float speed = 0.1;
    static int  bufferMode = 1;

    main(int argc, char **argv)
    {
      EZ_Widget *frame, *canvas, *slider, *cbtn;
      /*
       * Initialize EZWGL, don't forget to
       * initialize the graphics library also.
       */
      EZ_Initialize(argc, argv, 1);      /* notice the 1        */
      /*
       * canvases do not resize propertly as toplevel
       * widgets (bug!) It is recommended to put it
       * under a frame at least for now.
       */
      frame = EZ_CreateWidget(EZ_WIDGET_FRAME, NULL,
                             EZ_FILL_MODE, EZ_FILL_BOTH,
                             0);
      canvas = EZ_CreateWidget(EZ_WIDGET_3D_CANVAS, frame,
                               EZ_ORIENTATION,   EZ_VERTICAL_BOTTOM,
                               EZ_WIDTH_HINT,    320,
                               EZ_HEIGHT_HINT,   320,
                               EZ_EVENT_HANDLER, eventHandler, NULL,
                               0);
      slider = EZ_CreateWidget(EZ_WIDGET_VERTICAL_SLIDER, frame,
                               EZ_LABEL_STRING,      "speed",
                               EZ_SLIDER_RANGE,      0.0, 10.0,
                               EZ_SLIDER_INIT_VALUE, 1.0,
                               EZ_CALLBACK,          sliderCallBack, &speed,
                               0);

      /* create a button to toggle double buffer on/off */
      cbtn = EZ_CreateWidget(EZ_WIDGET_CHECK_BUTTON, canvas,
                             EZ_LABEL_STRING,        "Turn DoubleBuffer On/Off",
                             EZ_CHECK_BUTTON_ON_VALUE,  0,
                             EZ_CHECK_BUTTON_OFF_VALUE, 1,
                             EZ_CHECK_BUTTON_ON_OFF,    EZ_ON,
                             EZ_BORDER_WIDTH,           2,
                             EZ_BORDER_TYPE,            EZ_BORDER_RAISED,
                             EZ_CALLBACK,               cbtnCallBack, NULL,
                             0);
      /*
       * now display the canvas. One must first display
       * a 3DCanvas before calling any GL functions !!!
       */
      EZ_DisplayWidget(canvas);

      /* now setup global GL attributes */
      EZ_RGBMode();                 /* we are using RGB mode  */
      EZ_AutoSelectBackBuffer();    /* select a back buffer   */
      EZ_DrawBuffer(EZ_BACK);/* always draw into the back buf */

      /*
       * We'll draw a 2D polygon, so we don't have to setup
       * a complex projection matrix. The default matrix mode
       * is EZ_MODELVIEW. We just set the projection matrix
       * on this default matrix stack.
       */
      EZ_LoadIdentity();            /* clear the top mtx 2 id */
      EZ_Ortho2(0.0,10.0,-1.3,1.3); /* project the unit cube  */

      /*
       * We don't draw anything here, let the
       * event handler handle the drawing
       */
      while(1)
        {
          EZ_ServiceEvents();
          EZ_DrawBuffer(bufferMode == 0? EZ_FRONT: EZ_BACK);
          draw(canvas);
          if(bufferMode != 0) EZ_SwapBuffers();
        }
    }

    static void draw(EZ_Widget *canvas)
    {
      static float shift = 0.0;
      float  t, x, y;
      int    i;

      EZ_Clear(EZ_COLOR_BUFFER_BIT); /* clear the frame buffer */
      EZ_Color3f(1.0,1.0,0.0);

      EZ_Begin(EZ_LINE_STRIP);       /* start a polyline       */

      t = shift;
      shift += speed;
      x = 0.0;

      for(i = 0; i < 1000; i++)
        {
          y = sin(t+x);
          x += 0.01;

          EZ_Vertex2f(x, y);
        }
      EZ_End();
    }
    /*
     * the event handler. It should handle at least the
     * EZ_REDRAW event and the EZ_RESIZE.
     */
    static void eventHandler(EZ_Widget *canvas, void *data,
                             int eventType, XEvent *xevent)
    {
      switch(eventType)
        {
        case EZ_REDRAW:
        case EZ_RESIZE:
          draw(canvas);
          if(bufferMode != 0) EZ_SwapBuffers();
          break;
        case EZ_KEY_PRESS:
          if(EZ_PressedKey == EZ_ESCAPE_KEY) exit(0);
          break;
        default:
          break;
        }
    }

    static void sliderCallBack(EZ_Widget *slider, void *data)
    {
      float *f = (float *)data;
      *f = 0.05 * EZ_GetSliderValue(slider);
    }

    static void cbtnCallBack(EZ_Widget *cbtn, void *data)
    {
      EZ_GetCheckButtonState(cbtn, &bufferMode);
    }
    /*************** Example G2 ******************************************/

HTML Documentation Maintainance:`Arturo Espinosa <arturo@nuclecu.unam.mx>`