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.
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)
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);
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
.
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.
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 ******************************************/