Chapter 3. After toogl: How to Finish Porting to OpenGL
Prev |  | Next

## Chapter 3. After `toogl`: How to Finish Porting to OpenGL

After you run your IRIS GL program through `toogl`, you can use this chapter to find out how to replace IRIS GL calls that `toogl` didn't translate completely or correctly. To get the most out of this discussion, refer to the reference pages as necessary.

The chapter discusses these topics:

- “Header Files”

- “Porting greset()”

- “Porting IRIS GL get* Commands”

- “Porting Commands That Required Current Graphics Positions”

- “Porting Screen and Buffer Clearing Commands”

- “Porting Matrix and Transformation Calls”

- “Porting Drawing Commands”

- “Porting Color, Shading, and Writemask Commands”

- “Porting Pixel Operations”

- “Porting Depth Cueing and Fog Commands”

- “Porting Curve and Surface Commands”

- “Porting Antialiasing Calls”

- “Porting Display Lists”

- “Porting defs, binds, and sets: Replacing `Tables' of Stored Definitions”

- “Porting Texture Calls”

- “Porting Picking Calls”

- “Porting Feedback Calls”

- “Porting RealityEngine Graphics Features”

- “OpenGL Extensions”

## Header Files

`toogl` doesn't replace header files for you, so you have to replace them yourself. This section lists the files your IRIS GL program probably used and the OpenGL files to replace them with.

Table 3-1. Include Lines in IRIS GL and OpenGL Programs

IRIS GL Include Lines | OpenGL Include Lines
--- | ---
#include <gl/gl.h> #include <gl/device.h> #include <gl/get.h> | #include <GL/gl.h> #include <GL/glu.h> /* X header files start here*/ #include <Xm/Xm.h> #include <Xm/Frame.h> #include <Xm/Form.h> #include <X11/StringDefs.h> #include <X11/keysym.h>

If you use the GLUT library, you also have to include the GLUT header file:

    #include <GL/glut.h>

If you use the Motif widget, replace the include lines as indicated in Table 3-2.

Table 3-2. Include Lines for IRIS GL and OpenGL Motif Widgets

IRIS GL Motif Widget Include Lines | OpenGL Motif Widget Include Lines
--- | ---
For the IRIS IM version of the widget: #include <X11/Xirisw/GlxMDraw.h> | For the IRIS IM version of the widget: #include <GL/GLwMDrawA.h>
For the generic version of the widget: #include <X11/Xirisw/GLxDraw.h> | For the generic version of the widget: #include <GL/GLwDrawA.h>

If you're using Xlib and OpenGL/X calls, add

    #include <GL/glx.h>

## Porting greset()

OpenGL replaces the functionality of `greset()` with the commands `glPushAttrib()` and `glPopAttrib()`. Use these commands to save and restore groups of state variables.

Call `glPushAttrib()` to indicate which groups of state variables to push onto an attribute stack by taking a bitwise OR of symbolic constants, as follows:

    void glPushAttrib( GLbitfield mask );

The attribute stack has a finite depth of at least 16.

The `glPushAttrib()` and `glPopAttrib()` calls push and pop the server attribute stacks. In OpenGL 1.1, you can also use the functions `glPushClientAttrib()` and `glPopClientAttrib()` to push and pop the client attribute stack.

Each constant refers to a group of state variables. Table 3-3 shows the attribute groups with their corresponding symbolic constant names. For a complete list of the OpenGL state variables associated with each constant, see the `glPushAttrib` reference page.

Table 3-3. State Attribute Groups

Attribute | Constant
--- | ---
accumulation buffer clear value | GL_ACCUM_BUFFER_BIT
color buffer | GL_COLOR_BUFFER_BIT
current | GL_CURRENT_BIT
depth buffer | GL_DEPTH_BUFFER_BIT
enable | GL_ENABLE_BIT
evaluators | EGL_VAL_BIT
fog | GL_FOG_BIT
GL_LIST_BASE setting | GL_LIST_BIT
hint variables | GL_HINT_BIT
lighting variables | GL_LIGHTING_BIT
line drawing mode | GL_LINE_BIT
pixel mode variables | GL_PIXEL_MODE_BIT
point variables | GL_POINT_BIT
polygon | GL_POLYGON_BIT
polygon stipple | GL_POLYGON_STIPPLE_BIT
scissor | GL_SCISSOR_BIT
stencil buffer | GL_STENCIL_BUFFER_BIT
texture | GL_TEXTURE_BIT
transform | GL_TRANSFORM_BIT
viewport | GL_VIEWPORT_BIT
— | GL_ALL_ATTRIB_BITS
pixel storage modes | GL_CLIENT_PIXEL_STORE_BITS (1.1 only)
vertex arrays and enables | GL_CLIENT_VERTEX_ARRAY_BIT (1.1 only)

To restore the values of the state variables to those saved with the last `glPushAttrib()`, call `glPopAttrib()`. The variables you didn't save remain unchanged.

## Porting IRIS GL get* Commands

IRIS GL get* calls are of this form:

    int getthing();
    int getthings( int *a, int *b);

Your IRIS GL program probably includes calls that look like the following:

    thing = getthing();
    if(getthing() == THING) { /* stuff */ }
    getthings (&a, &b);

OpenGL uses `glGet*()` calls for equivalent functionality; they look like this:

    void glGetIntegerfv(NAME_OF_THING, &thing);

Table A-1 lists the IRIS GL get functions with their OpenGL equivalents.

In general, this guide lists various parameters for `glGet*()` calls in the sections that discuss topics related to those parameters. To see the parameter values related to matrices, for example, see “Porting Matrix and Transformation Calls”.

There are other functions to query the OpenGL state, such as `glGetClipPlane()` and `glGetLight()`. These commands are discussed in the sections on related calls, and also in the reference pages.

### About glGet*()

There are four types of `glGet*()` functions:

- `glGetBooleanv()`

- `glGetIntegerv()`

- `glGetFloatv()`

- `glGetDoublev()`

The functions have this syntax:

    glGet<Datatype>v( value, *data )

value is of type GLenum and data of type GLdatatype. If you issue a `glGet*()` call that returns types different from the expected types, each type is converted appropriately. For a complete list of parameters, see the `glGet` reference page.

In addition to the basic glGet*() function, there are a number of special purpose information retrieval functions: `glGetClipPlane`, `glGetError`, `glGetLight`, `glGetMap`, `glGetMaterial`, `glGetPixelMap`, `glGetPointerv`, `glGetPolygonStipple`, `glGetString`, `glGetTexEnv`, `glGetTexGen`, `glGetTexImage`, `glGetTexlevelParameter`, `glGetTexParameter`.

### glGet*() Conventions Used in This Book

For the sake of brevity, this guide usually shortens the reference to the form

    glGet*(GL_GET_TYPE)

For example,

    glGetIntegerv(GL_VIEWPORT, *params);

is abbreviated as

    glGet*(GL_VIEWPORT);

in tables and text (but not in code examples).

## Porting Commands That Required Current Graphics Positions

OpenGL doesn't maintain a current graphics position. IRIS GL commands that depend on the current graphics position, such as `move()`, `draw()`, and `rmv()`, have no equivalents in OpenGL.

Older versions of IRIS GL included drawing commands that relied upon the current graphics position, though their use was discouraged in more recent versions. You have to reimplement parts of your program if you relied on the current graphics position in any way, or used any of the following routines:

- `draw()` and `move()`

- `pmv()`, `pdr()`, and `pclos()`

- `rdr()`, `rmv()`, `rpdr()`, and `rpmv()`

- `getgpos()`

OpenGL has a concept of raster position that corresponds to the IRIS GL current character position. See “Porting Pixel Operations” for more information.

## Porting Screen and Buffer Clearing Commands

OpenGL replaces a variety of IRIS GL `clear()` calls (such as `zclear()`, `aclear()`, `sclear()`, and so on) with one: `glClear()`. Specify exactly what you want to clear by passing masks to `glClear()`.

When porting screen and buffer clearing commands, consider the following issues:

- OpenGL maintains clear colors separately from drawing colors, with calls like `glClearColor()` and `glClearIndex()`. Be sure to set the clear color for each buffer before making a clear call.

- Since `toogl` has no concept of context, it cannot correctly translate color calls immediately preceding clear calls into `glClearColor()` calls. You have to translate these calls explicitly. For example, suppose your program clears the viewport as follows:

      color(BLACK);
      clear();

  `toogl` translates those two lines as follows:

      glIndex(BLACK);
      glClear(GL_COLOR_BUFFER_BIT);

  A better translation of this fragment the following:

      glClearIndex(0);
      glClear(GL_COLOR_BUFFER_BIT);

  Remember that IRIS GL color constants, such as BLACK, are not defined in OpenGL.

- Instead of using one of several differently named clear calls, you now clear several buffers with one call, `glClear()`, by ORing together buffer masks. For example, `czclear()` is replaced by

      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )

- IRIS GL respects the polygon stipple and the color write mask. OpenGL ignores the polygon stipple but respects the write mask. `czclear()` ignored both the polygon stipple and the write mask.

Table 3-4 lists the various clear calls with their IRIS GL equivalents.

Table 3-4. Calls for Clearing the Screen

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
acbuf(AC_CLEAR) | glClear(GL_ACCUM_BUFFER_BIT) | Clear the accumulation buffer.
— | glClearColor() | Set the RGBA clear color.
— | glClearIndex() | Set the clear color index.
clear() | glClear(GL_COLOR_BUFFER_BIT) | Clear the color buffer.
— | glClearDepth() | Specify the clear value for the depth buffer.
zclear() | glClear(GL_DEPTH_BUFFER_BIT) | Clear the depth buffer.
czclear() | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) | Clear the color buffer and the depth buffer.
— | glClearAccum() | Specify clear values for the accumulation buffer.
— | glClearStencil() | Specify the clear value for the stencil buffer.
sclear() | glClear(GL_STENCIL_BUFFER_BIT) | Clear the stencil buffer.

If your IRIS GL code used both `gclear()` and `sclear()`, you can instead use a single `glClear()` call. As a result, your program's performance may improve.

## Porting Matrix and Transformation Calls

When porting matrix and transformation calls, consider the following issues:

- There is no single-matrix mode. OpenGL is always in double-matrix mode.

- Angles are now measured in degrees, instead of tenths of degrees.

- Projection matrix calls, like `glFrustum()` and `glOrtho()`, now multiply with the current matrix, instead of being loaded onto the current matrix.

- The OpenGL call `glRotate()` is different from `rotate()`. `glRotate()` lets you rotate around any arbitrary axis, instead of being confined to the x, y, and z axes. But you probably have to port `rotate()` calls explicitly, because `toogl` often doesn't translate them correctly. For example, `toogl` might translate

      rotate(200*(i+1), 'z');

  into

      glRotate(.1*(200*(i+1)), ( 'z')=='x', ( 'z')=='y',
                               ( 'z')=='z');

  `toogl` correctly switched to degrees from tenths of degrees, but didn't correctly handle the replacement of `z` with a vector for the z-axis. A better translation is

      glRotate(.1*(200*(i+1), 0.0, 0.0, 1.0);

- OpenGL documentation presents matrices in a manner more consistent with standard usage in linear algebra than did IRIS GL documentation. Specifically, in IRIS GL documentation, vectors are treated as rows, and a matrix is applied to a vector on the right of the vector. `multmatrix()` replaces the current matrix C with C' = MC. In OpenGL documentation, vectors are treated as columns, and a matrix applies to a vector on the left of the vector. `glMultMatrix()` computes C' = CM.

  A generic IRIS GL translation is shown in the equation in Figure 3-1.

  Figure 3-1. Generic IRIS GL Translation

  A generic OpenGL translation is shown in the equation in Figure 3-2.

  Figure 3-2. Generic OpenGL Translation

  The important thing is that this is a change in documentation only—OpenGL matrices are completely compatible with the ones in IRIS GL except that they are stored in column-major order. So, if you want the matrix shown in the equation in Figure 3-3 in your OpenGL application, you would declare it as follows:

      float mat[16] = {a, e, i, m, b, f, j, n, c, g,
                       k, o, d, h, l, p}

  Figure 3-3. OpenGL Matrix Example

- OpenGL has no equivalent to the `polarview()` call. You can replace such a call with a translation and three rotations. For example, the IRIS GL call

      polarview(distance, azimuth, incidence, twist);

  translates to

      glTranslatef( 0.0, 0.0, -distance);
      glRotatef( -twist * 10.0, 0.0, 0.0, 1.0);
      glRotatef( -incidence * 10.0, 1.0, 0.0, 0.0);
      glRotatef( -azimuth * 10.0, 0.0, 0.0, 1.0);

- The replacement for the `lookat()` call, `gluLookAt()`, takes an up vector instead of a twist angle. `toogl` doesn't translate this call correctly, so you have to port explicitly. See the `gluLookAt` reference page for more information.

Table 3-5 lists the OpenGL matrix calls and their IRIS GL equivalents.

Table 3-5. Matrix Operations

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
mmode() | glMatrixMode() | Set current matrix mode.
— | glLoadIdentity() | Replace current matrix with the identity matrix.
loadmatrix() | glLoadMatrixf(), glLoadMatrixd() | Replace current matrix with the specified matrix.
multmatrix() | glMultMatrixf(), glMultMatrixd() | Post-multiply current matrix with the specified matrix (note that multmatrix() pre-multiplied).
mapw(), mapw2() | gluUnProject() | Project world space coordinates to object space (see also gluProject()).
ortho() | glOrtho() | Multiply current matrix by an orthographic projection matrix.
ortho2() | gluOrtho2D() | Define a two-dimensional orthographic projection matrix.
perspective() | gluPerspective() | Define a perspective projection matrix.
picksize() | gluPickMatrix() | Define a picking region.
popmatrix() | glPopMatrix() | Pop current matrix stack, replacing the current matrix with the one below it.
pushmatrix() | glPushMatrix() | Push current matrix stack down by one, duplicating the current matrix.
rotate(), rot() | glRotated(), glRotatef() | Rotate current coordinate system by the given angle about the vector from the origin through the given point. Note that rotate() rotated only about the x, y, and z axes.
scale() | glScaled(),glScalef() | Multiply current matrix by a scaling matrix.
translate() | glTranslatef(), glTranslated() | Move coordinate system origin to the specified point by multiplying the current matrix by a translation matrix.
window() | glFrustum() | Given coordinates for clipping planes, multiply the current matrix by a perspective matrix.

OpenGL has three matrix modes, which are set with `glMatrixMode()`. Table 3-6 lists the IRIS GL `mmode()` arguments in the first column and the corresponding arguments to `glMatrixMode()` in the second column.

Table 3-6. Matrix Modes

IRIS GL Matrix Mode | OpenGL Mode | Meaning | Min. Stack Depth
--- | --- | --- | ---
MTEXTURE | GL_TEXTURE | Operate on the texture matrix stack. | 2
MVIEWING | GL_MODELVIEW | Operate on the modelview matrix stack. | 32
MPROJECTION | GL_PROJECTION | Operate on the projection matrix stack. | 2

### Porting MSINGLE Mode Code

OpenGL has no equivalent for MSINGLE, single-matrix mode. Though use of this mode has been discouraged, it was the default for IRIS GL and your program may have used it. If it did, you have to reimplement part of it. OpenGL is always in double-matrix mode, and is initially in GL_MODELVIEW mode.

Most IRIS GL code in MSINGLE mode looks as follows:

    ...
    projectionmatrix();
    ...

`projectionmatrix()` is one of the following: `ortho()`, `ortho2()`, `perspective()`, `window()`. To port to OpenGL, replace the MSINGLE mode `projectionmatrix()` call by the following pseudo-code:

    ...
    glMatrixMode( GL_PROJECTION );
    glLoadMatrix( identity matrix );
    [one of these calls:
            glFrustrum(), glOrtho(), glOrtho2(), gluPerspective()];
    glMatrixMode( GL_MODELVIEW );
    glLoadMatrix( identity matrix );

### Porting get* Calls for Matrices and Transformations

Table 3-7 maps IRIS GL matrix queries to OpenGL matrix queries.

Table 3-7. Arguments for Transformation Matrix Queries

IRIS GL Matrix Query | OpenGL glGet*() Matrix Query | Meaning
--- | --- | ---
getmmode() | GL_MATRIX_MODE | Return the current matrix mode.
getmatrix() in MVIEWING mode | GL_MODELVIEW_MATRIX | Return a copy of the current modelview matrix.
getmatrix() in MPROJECTION mode | GL_PROJECTION_MATRIX | Return a copy of the current projection matrix.
getmatrix() in MTEXTURE mode | GL_TEXTURE_MATRIX | Return a copy of the current texture matrix.
— | GL_MAX_MODELVIEW_STACK_DEPTH | Return maximum supported depth of modelview matrix stack.
— | GL_MAX_PROJECTION_STACK_DEPTH | Return maximum supported depth of projection matrix stack.
— | GL_MAX_TEXTURE_STACK_DEPTH | Return maximum supported depth of texture matrix stack.
— | GL_MODELVIEW_STACK_DEPTH | Return number of matrices on modelview stack.
— | GL_PROJECTION_STACK_DEPTH | Return number of matrices on projection stack.
— | GL_TEXTURE_STACK_DEPTH | Return number of matrices on texture stack.

### Porting Viewports, Screenmasks, and Scrboxes

The following IRIS GL calls have no direct OpenGL equivalent:

- `reshapeviewport()`

- `scrbox()`, `getscrbox()`

The IRIS GL `viewport()` call had as parameters the x coordinates (in pixels) for the left and right of the viewport rectangle and the y coordinates for the top and bottom. The OpenGL `glViewport()` call has as parameters the x and y coordinates (in pixels) of the lower left corner of the viewport rectangle, as well as the rectangle's width and height.

Table 3-8 lists the OpenGL equivalents for viewport commands.

Table 3-8. Viewport Calls

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
viewport(left, right, bottom, top) | glViewport(x, y, width, height) | Set the viewport.
popviewport() pushviewport() | glPopAttrib() glPushAttrib(GL_VIEWPORT_BIT) | Push and pop the stack.
getviewport() | glGet*(GL_VIEWPORT) | Return viewport dimensions.

### Porting Clipping Planes

OpenGL implements clipping planes the way IRIS GL did, though you can now also query clipping planes. Table 3-9 lists the OpenGL equivalents to IRIS GL calls.

Table 3-9. Clipping Plane Calls

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
clipplane(i, CP_ON, params) | glEnable(GL_CLIP_PLANEi) | Enable clipping on plane i.
clipplane(i, CP_DEFINE, plane) | glClipPlane( GL_CLIP_PLANE i, plane) | Define clipping plane.
— | glGetClipPlane() | Return clipping plane equation.
— | glIsEnabled( GL_CLIP_PLANEi) | Return true if clip plane i is enabled.
scrmask() | glScissor() | Define the scissor box.
getscrmask() | glGet*(GL_SCISSOR_BOX) | Return the current scissor box.

To turn on the scissor test, call `glEnable()` with GL_SCISSOR_BOX as the parameter.

## Porting Drawing Commands

The following sections discuss how to port IRIS GL drawing primitives, discussing the following topics:

- “Porting the IRIS GL Sphere Library”

- “Porting v() Commands”

- “Porting bgn/end Commands”

- “Porting Points”

- “Porting Lines”

- “Porting Polygons and Quadrilaterals”

- “Porting Tessellated Polygons”

- “Porting Triangles”

- “Porting Arcs and Circles”

- “Porting Spheres”

### Porting the IRIS GL Sphere Library

The sphere library that worked with IRIS GL isn't available for OpenGL. You can replace sphere library calls with quadrics routines from the GLU library or with the GLUT functions for geometric object rendering. Refer to the OpenGL Programming Guide and the GLU reference pages in the OpenGL Reference Manual for details on using the GLU library. Table 3-10 summarizes OpenGL quadrics calls.

Table 3-10. Calls for Drawing Quadrics

OpenGL Call | Meaning
--- | ---
gluNewQuadric() | Create a new quadric object.
gluDeleteQuadric() | Delete a quadric object.
gluQuadricCallback() | Associate a callback with a quadric object, for error handling.
gluQuadricNormals() | Specify normals: no normals, one per face, or one per vertex.
gluQuadricOrientation() | Specify direction of normals: outward or inward.
gluQuadricTexture() | Turn texture coordinate generation on or off.
gluQuadricDrawstyle() | Specify drawing style: polygons, lines, points, and so on.
gluSphere() | Draw a sphere.
gluCylinder() | Draw a cylinder or cone.
gluPartialDisk() | Draw an arc.
gluDisk() | Draw a circle or disk.

You can use one quadric object for all quadrics you'd like to render in similar ways. The code fragment in Example 3-1 uses two quadrics objects to draw four quadrics, two of them textured.

Example 3-1. Drawing Quadrics Objects

    GLUquadricObj    *texturedQuad, *plainQuad;

    texturedQuad = gluNewQuadric(void);
    gluQuadricTexture(texturedQuad, GL_TRUE);
    gluQuadricOrientation(texturedQuad, GLU_OUTSIDE);
    gluQuadricDrawStyle(texturedQuad, GLU_FILL);

    plainQuad = gluNewQuadric(void);
    gluQuadricDrawStyle(plainQuad, GLU_LINE);

    glColor3f (1.0, 1.0, 1.0);

    gluSphere(texturedQuad, 5.0, 20, 20);
    glTranslatef(10.0, 10.0, 0.0);
    gluCylinder(texturedQuad, 2.5, 5, 5, 10, 10);
    glTranslatef(10.0, 10.0, 0.0);
    gluDisk(plainQuad, 2.0, 5.0, 10, 10);
    glTranslatef(10.0, 10.0, 0.0);
    gluSphere(plainQuad, 5.0, 20, 20);

### Porting v() Commands

In IRIS GL, you use variations on the `v()` call to specify vertices. The OpenGL `glVertex()` call is a direct successor of this call:

    glVertex2[d|f|i|s][v]( x, y );

    glVertex3[d|f|i|s][v]( x, y, z);
    glVertex4[d|f|i|s][v]( x, y, z, w);

`glVertex()` takes suffixes the same way other OpenGL calls do. The vector versions of the call take arrays of the proper size as arguments. In the 2D version, z = 0 and w = 1. In the 3D version, w = 1.

### Porting bgn/end Commands

IRIS GL uses the begin/end paradigm but has a different call for each graphics primitive. For example, `bgnpolygon()` and `endpolygon()` draw polygons, and`bgnline()` and`endline()` draw lines. In OpenGL, you use the `glBegin()`/`glEnd()` structure. OpenGL draws most geometric objects by enclosing a series of calls that specify vertices, normals, textures, and colors between pairs of `glBegin()` and `glEnd()` calls.

    void glBegin( GLenum mode) ;
       /* vertex list, colors, normals, textures, materials */
    void glEnd( void );

`glBegin()` takes a single argument that specifies the drawing mode, and thus the primitive. Here's an OpenGL code fragment that draws a polygon and then a line:

    glBegin( GL_POLYGON) ;
       glVertex2f(20.0, 10.0);
       glVertex2f(10.0, 30.0);
       glVertex2f(20.0, 50.0);
       glVertex2f(40.0, 50.0);
       glVertex2f(50.0, 30.0);
       glVertex2f(40.0, 10.0);
    glEnd();
    glBegin( GL_LINES ) ;
       glVertex2i(100,100);
       glVertex2i(500,500);
    glEnd();

In OpenGL, you draw different geometric objects by specifying different arguments to `glBegin()`. These arguments are listed in Table 3-11 below, along with the IRIS GL calls they replace (if any). There is no limit to the number of vertices you can specify between a `glBegin()`/`glEnd()` pair.

Table 3-11. Calls for Drawing Primitives

IRIS GL Call | Value of glBegin() Mode | Meaning
--- | --- | ---
bgnpoint() | GL_POINTS | Individual points
bgnline() | GL_LINE_STRIP | Series of connected line segments
bgnclosedline() | GL_LINE_LOOP | Series of connected line segments, with a segment added between first and last vertices
— | GL_LINES | Pairs of vertices interpreted as individual line segments
bgnpolygon() | GL_POLYGON | Boundary of a simple convex polygon
— | GL_TRIANGLES | Triples of vertices interpreted as triangles
bgntmesh() | GL_TRIANGLE_STRIP | Linked strips of triangles
— | GL_TRIANGLE_FAN | Linked fans of triangles
— | GL_QUADS | Quadruples of vertices interpreted as quadrilaterals
bgnqstrip() | GL_QUAD_STRIP | Linked strips of quadrilaterals

For a detailed discussion of the differences between triangle meshes, strips, and fans, see “Porting Triangles”.

In addition to specifying vertices inside a `glBegin()`/`glEnd()` pair, you can also specify a current normal, current texture coordinates, and a current color. Table 3-12 lists the commands valid inside a `glBegin()`/`glEnd()` pair.

Table 3-12. Valid Commands Inside a Begin/End Structure

IRIS GL Call | OpenGL Equivalent | Meaning
--- | --- | ---
v2*(), v3*(), v4*() | glVertex*() | Set vertex coordinates.
RGBcolor(), cpack() | glColor*() | Set current color.
color(), colorf() | glIndex*() | Set current color index.
n3f() | glNormal*() | Set normal vector coordinates.
— | glEvalCoord() | Evaluate enabled one- and two-dimensional maps.
callobj() | glCallList(), glCallLists() | Execute display list(s).
t2() | glTexCoord() | Set texture coordinates.
— | glEdgeFlag() | Control drawing edges.
lmbind() | glMaterial() | Set material properties.

If you use any other OpenGL command inside a `glBegin()`/`glEnd()` pair, results are unpredictable and an error may result.

### Porting Points

OpenGL has no command to draw a single point. Otherwise, porting point calls is straightforward. Table 3-13 lists commands for drawing points.

Table 3-13. Calls for Drawing Points

IRIS GL Call | OpenGL Equivalent | Meaning
--- | --- | ---
pnt() | — | Draw a single point.
bgnpoint(), endpoint() | glBegin(GL_POINTS), glEnd() | Interpret vertices as points.
pntsize() | glPointSize() | Set point size in pixels.
pntsmooth() | glEnable(GL_POINT_SMOOTH) | Turn on point antialiasing (see “Porting Antialiasing Calls”).

See the `glPointSize` reference page for information about related `glGet*()` commands.

### Porting Lines

Porting code that draws lines is fairly straightforward, though you should note the differences in the way OpenGL does stipples.

Table 3-14. Calls for Drawing Lines

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
bgnclosedline(), endclosedline() | glBegin(GL_LINE_LOOP) glEnd() | Draw a closed line.
bgnline() | glBegin(GL_LINE_STRIP) | Draw line segments.
linewidth() | glLineWidth() | Set line width.
getlwidth() | glGet*(GL_LINE_WIDTH) | Return current line width.
deflinestyle() setlinestyle() | glLineStipple(factor, pattern) | Specify a line stipple pattern.
lsrepeat() | factor argument of glLineStipple() | Set a repeat factor for the line style.
getlstyle() | glGet*(GL_LINE_STIPPLE_PATTERN) | Return line stipple pattern.
getlsrepeat() | glGet*(GL_LINE_STIPPLE_REPEAT) | Return repeat factor.
linesmooth(), smoothline() | glEnable(GL_LINE_SMOOTH) | Turn on line antialiasing (see “Porting Antialiasing Calls”).

There are no tables for line stipples. OpenGL maintains only one line stipple pattern. You can use `glPushAttrib()` and `glPopAttrib()` to switch between different stipple patterns.

Old-style line style routines are not supported by OpenGL. If you used the calls: `draw()`, `lsbackup()`, `getlsbackup()`, `resetls()`, `getresetls()`, reimplement that part of your program.

For information on drawing antialiased lines, see “Porting Antialiasing Calls”.

### Porting Polygons and Quadrilaterals

When porting polygons and quadrilaterals, consider the following issues:

- There is no direct equivalent for `concave(TRUE)`. Consider using the GLU tessellation routines described in “Porting Tessellated Polygons”.

- Polygon modes are now set differently.

- These older polygon drawing calls have no direct equivalents in OpenGL:

  - the `poly()` family of routines

  - the `polf()` family of routines

  - `pmv()`, `pdr()`, and `pclos()`

  - `rpmv()` and `rpdr()`

  - `splf()`

  - `spclos()`

  If you used these calls, reimplement that part of the program using `glBegin(GL_POLYGON)`.

Table 3-15 lists the OpenGL equivalents to IRIS GL polygon drawing calls.

Table 3-15. Calls for Drawing Polygons

IRIS GL Call | OpenGL Equivalent | Meaning
--- | --- | ---
bgnpolygon(), endpolygon() | glBegin(GL_POLYGON), glEnd() | Vertices define boundary of a simple convex polygon.
— | glBegin(GL_QUADS), glEnd() | Interpret quadruples of vertices as quadrilaterals.
bgnqstrip(), endqstrip() | glBegin(GL_QUAD_STRIP), glEnd() | Interpret vertices as linked strips of quadrilaterals.
— | glEdgeFlag() |
polymode() | glPolygonMode() | Set polygon drawing mode.
rect(), rectf() | glRect() | Draw a rectangle.
sbox(), sboxf() | — | Draw a screen-aligned rectangle.

#### Setting Polygon Modes

The call for setting the polygon mode has changed slightly. The OpenGL call `glPolygonMode()` allows you to specify which side of a polygon (front or back) the mode applies to. Its syntax is

    void glPolygonMode( GLenum face, GLenum mode )

face is one of the following:

GL_FRONT | Mode applies to front-facing polygons.
GL_BACK | Mode applies to back-facing polygons.
GL_FRONT_AND_BACK | Mode applies to both front- and back-facing polygons.

The equivalents to IRIS GL `polymode()` calls would use GL_FRONT_AND_BACK. Table 3-16 lists IRIS GL polygon modes and the corresponding OpenGL modes.

Table 3-16. Polygon Modes

IRIS GL Mode | OpenGL Mode | Meaning
--- | --- | ---
PYM_POINT | GL_POINT | Draw vertices as points.
PYM_LINE | GL_LINE | Draw boundary edges as line segments.
PYM_FILL | GL_FILL | Draw polygon interior filled.
PYM_HOLLOW | — | Fill only interior pixels at the boundaries.

#### Setting Polygon Stipples

When porting polygon stipples, consider the following issues:

- There are no tables for polygon stipples. OpenGL keeps only one stipple pattern. You can use display lists to store different stipple patterns.

- The polygon stipple bitmap size is always a 32 x 32 bit pattern.

- Stipple encoding is affected by `glPixelStore()`. See “Porting Pixel Operations” for more information.

Table 3-17 lists polygon stipple calls.

Table 3-17. Polygon Stipple Calls

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
defpattern() | glPolygonStipple() | Set the stipple pattern.
setpattern() | — | OpenGL keeps only one polygon stipple pattern.
getpattern() | glGetPolygonStipple() | Return the stipple bitmap (used to return an index).

Enable and disable polygon stippling by passing GL_POLYGON_STIPPLE as an argument to `glEnable()` and `glDisable()`.

Example 3-2 shows an OpenGL code fragment that demonstrates polygon stippling.

Example 3-2. OpenGL Polygon Stippling

    /*  polys.c  */
    #include <GL/gl.h>
    #include <GL/glu.h>

    void display(void)
    {
        GLubyte fly[] = {
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60,
          0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,
          0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,
          0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22,
          0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
          0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
          0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
          0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,
          0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,
          0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,
          0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,
          0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30,
          0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,
          0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,
          0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08
        };
        GLubyte halftone[] = {
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
          0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
        };

        glClear (GL_COLOR_BUFFER_BIT);
        glColor3f (1.0, 1.0, 1.0); /* draw all polys in white */

    /*  draw 1 solid unstippled rectangle, then 2 stippled ones*/
        glRectf (25.0, 25.0, 125.0, 125.0);
        glEnable (GL_POLYGON_STIPPLE);
        glPolygonStipple (fly);
        glRectf (125.0, 25.0, 225.0, 125.0);
        glPolygonStipple (halftone);
        glRectf (225.0, 25.0, 325.0, 125.0);
        glDisable (GL_POLYGON_STIPPLE);
        glFlush ();
    }

### Porting Tessellated Polygons

The GLU has routines you can use to draw concave polygons. You no longer just use `concave(TRUE)` and then `bgnpolygon()`.

To draw a concave polygon with OpenGL, follow these steps:

1. Create a tesselation object.

2. Define callbacks that will be used to process the triangles generated by the tessellator.

3. Specify the concave polygon to be tessellated.

Table 3-18 lists the calls for drawing tessellated polygons.

Table 3-18. Tessellated Polygon Calls

GLU Call | Meaning
--- | ---
`gluNewTess`() | Create a new tessellation object.
`gluDeleteTess`() | Delete a tessellation object.
`gluTessCallback`() | —
`gluBeginPolygon`() | Begin the polygon specification.
`gluTessVertex`() | Specify a polygon vertex. Successive gluTessVertex() calls describe a closed contour.
`gluNextContour`() | Indicate that the next series of vertices describe a new contour.
`gluEndPolygon`() | End the polygon specification.

For details, see the reference pages for the commands in Table 3-18.

### Porting Triangles

OpenGL provides three ways to draw triangles: separate triangles, triangle strips, and triangle fans.

When porting triangles, consider the following issues:

- There's no OpenGL equivalent for `swaptmesh()`. Instead, use a combination of triangles, triangle strips, and triangle fans.

- If your IRIS GL program draws individual triangles by surrounding each triangle with a `bgntmesh()` / `endtmesh()` pair, surround the entire group of individual triangles with just one `glBegin(GL_TRIANGLES)` `/` `glEnd()` pair in your OpenGL program, for a noticeable performance increase.

Table 3-19 lists the commands for drawing triangles.

Table 3-19. Calls for Drawing Triangles

IRIS GL Call | Equivalent glBegin() Argument | Meaning
--- | --- | ---
— | GL_TRIANGLES | Triples of vertices interpreted as triangles.
bgntmesh(), endtmesh() | GL_TRIANGLE_STRIP | Linked strips of triangles.
— | GL_TRIANGLE_FAN | Linked fans of triangles.

### Porting Arcs and Circles

In OpenGL, filled arcs and circles are drawn with the same calls as unfilled arcs and circles. See the reference pages for specifics. Table 3-20 lists the IRIS GL arc and circle commands and the corresponding OpenGL (GLU) commands.

Table 3-20. Calls for Drawing Arcs and Circles

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
arc(), arcf() | gluPartialDisk() | Draw an arc.
circ(), circf() | gluDisk() | Draw a circle or disk.

The `gluPartialDisk()` call is different from the `arc()` call. See the `gluPartialDisk` reference page for complete information.

IRIS GL arcs and circles are called disks and partial disks in OpenGL. You can do some things with OpenGL disks and partial disks that you could not do with IRIS GL. See the OpenGL Programming Guide and the reference pages in the OpenGL Reference Manual for detailed information.

When porting arcs and circles, consider these issues:

- Angles are no longer measured in tenths of degrees, but simply in degrees.

- The start angle is measured from the positive y axis, and not from the x axis.

- The sweep angle is now clockwise instead of counterclockwise, as shown in Figure 3-4.

  Figure 3-4. Drawing Angles: Comparing IRIS GL and OpenGL

### Porting Spheres

When porting spheres, consider these issues:

- In OpenGL, you cannot control the type of primitives used to draw the sphere. Instead, you can control drawing precision by using the slices and stacks parameters. Slices are longitudinal; stacks are latitudinal.

- Spheres are now drawn centered at the origin. Instead of specifying the location, as you used to in `sphdraw()` calls, precede a `gluSphere()` call with a translation.

- The sphere library isn't yet available for OpenGL—see “Porting the IRIS GL Sphere Library” for more information about replacing sphere library calls.

Table 3-21 lists the IRIS GL calls for drawing spheres along with the corresponding GLU calls where available.

Table 3-21. Calls for Drawing Spheres

IRIS GL Call | GLU Call | Notes
--- | --- | ---
sphobj() | gluNewQuadric() | Create a new sphere object.
sphfree() | gluDeleteQuadric() | Delete sphere object and free memory used.
sphdraw() | gluSphere() | Draw a sphere.
sphmode() | — | Set sphere attributes.
sphrotmatrix() | — | Control sphere orientation.
sphgnpolys() | — | Return number of polygons in current sphere.

## Porting Color, Shading, and Writemask Commands

When porting color, shading, and writemask calls, note that color map implementation differs between OpenGL and IRIS GL and consider these issues:

- Although you can set color map indices with the OpenGL `glIndex()` call, OpenGL doesn't provide a routine for loading color map indices. See “Using X Color Maps” for an example code fragment that sets up a color map.

- Color values are normalized to their data type. See the `glColor` reference page for details.

- There is no simple equivalent for `cpack()`. You can use `glColor()` instead, but you have to port explicitly.

- Some calls to `c()` or `color()` may have to be translated to `glClearColor()` or `glClearIndex()` and not `glColor()` or `glIndex()`. See “Porting Screen and Buffer Clearing Commands” for details.

- The RGBA writemask is not for each bit, just for each component.

- IRIS GL provided defined color constants: BLACK, BLUE, RED, GREEN, MAGENTA, CYAN, YELLOW, and WHITE. OpenGL doesn't provide these constants and `toogl` doesn't translate them, so you have to port them explicitly.

### Porting Color Calls

Table 3-22 lists IRIS GL color calls and their OpenGL equivalents.

Table 3-22. Color Calls

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
c3*(), c4*() | glColor*() | Sets RGB color.
color(), colorf() | glIndex*() | Sets the color index.
getcolor() | glGet*(GL_CURRENT_INDEX) | Returns the current color index.
getmcolor() | XQueryColor() | Gets a copy of a colormap entry's RGB values.
gRGBcolor() | glGet*(GL_CURRENT_COLOR) | Gets the current RGB color values.
mapcolor() | XStoreColor() | See “Using X Color Maps”.
RGBcolor() | glColor() | Sets RGB color.
writemask() | glIndexMask() | Sets the color index mode color mask.
wmpack() RGBwritemask() | glColorMask() | Sets the RGB color mode mask.
getwritemask() | glGet*(GL_COLOR_WRITEMASK) glGet*(GL_INDEX_WRITEMASK) | Gets the color mask.
gRGBmask() | glGet*(GL_COLOR_WRITEMASK) | Gets the color mask.
zwritemask() | glDepthMask() | —

| Note: Be careful when replacing `zwritemask()` with `glDepthMask()`: `glDepthMask()` takes a boolean argument; `zwritemask()` takes a bitfield.

If you want to use multiple color maps, use the X colormap facilities. The functions `multimap()`, `onemap()`, `getcmmode()`, `setmap()`, and `getmap()` have no OpenGL equivalents.

### Porting Shading Models

Just like IRIS GL, OpenGL lets you switch between smooth (Gouraud) shading and flat shading. Table 3-23 lists the calls.

Table 3-23. Shading and Dithering

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
shademodel(FLAT) | glShadeModel(GL_FLAT) | Do flat shading.
shademodel(GOURAUD) | glShadeModel(GL_SMOOTH) | Do smooth shading.
getsm() | glGet*(GL_SHADE_MODEL) | Return current shade model.
dither(DT_ON) dither(DT_OFF) | glEnable(GL_DITHER) glDisable(GL_DITHER) | Turn dithering on/off.

Smooth shading and dithering are on by default, as in IRIS GL.

## Porting Pixel Operations

When porting pixel operations, consider the following issues:

- Logical pixel operations are not applied to RGBA color buffers. See the `glLogicOp` reference page for more information.

- In general, IRIS GL used the ABGR format for pixels (that is, with color components in the order Alpha, Blue, Green, Red), while OpenGL uses the RGBA format. Although `glPixelStore()` can reverse the order of bytes within a color component, it can't reverse the order of the components within a pixel; thus, it can't be used to convert IRIS GL pixels to OpenGL pixels. Instead, you must reverse the order of the components yourself.

- When porting `lrectwrite()` calls, be careful to note where `lrectwrite()` is writing (for instance, it could be writing to the depth buffer).

- If you wanted to read from the z-buffer in IRIS GL, you specified that buffer with `readsource()` and then used `lrectread()` or `rectread()` to do the reading. If you want to read from the z-buffer in OpenGL, you simply specify that buffer as a parameter to `glReadPixels()`.

OpenGL provides some additional flexibility in pixel operations. Table 3-24 lists calls for pixel operations.

Table 3-24. Pixel Operations

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
lrectread(), rectread(), readRGB() | glReadPixels() | Read a block of pixels from the frame buffer.
lrectwrite(), rectwrite() | glDrawPixels() | Write a block of pixels to the frame buffer.
rectcopy() | glCopyPixels() | Copy pixels in the frame buffer.
rectzoom() | glPixelZoom() | Specify pixel zoom factors for glDrawPixels() and glCopyPixels().
cmov() | glRasterPos() | Specify raster position for pixel operations.
readsource() | glReadBuffer() | Select a color buffer source for pixels.
pixmode() | glPixelStore() | Set pixel storage modes.
pixmode() | glPixelTransfer() | Set pixel transfer modes.
logicop() | glLogicOp() | Specify a logical operation for pixel writes.
— | glEnable(GL_LOGIC_OP) | Turn on pixel logic operations.

See the reference page for `glLogicOp` for a list of possible logical operations.

Here's a code fragment that shows a typical pixel write operation:

    unsigned long *packedRaster;
    ...
    packedRaster[k] = 0x00000000;
    ...
    lrectwrite(0, 0, xSize, ySize, packedRaster);

Here is how `toogl` translates the call to `lrectwrite()`:

    /* OGLXXX lrectwrite: see man page for glDrawPixels */
    glRasterPos2i(0,  0);
    glDrawPixels(( xSize)-(0)+1, ( ySize)-( 0)+1, GL_RGBA,
                 GL_UNSIGNED_BYTE, packedRaster);

After some tweaking, the finished code might look like this:

    glRasterPos2i(0, 0);
    glDrawPixels(xSize + 1, ySize + 1, GL_RGBA,
                 GL_UNSIGNED_BYTE, packedRaster);

## Porting Depth Cueing and Fog Commands

When porting depth cueing and fog commands, consider these issues:

- The fog calls have been restructured, so you have to rewrite them explicitly in most cases. The IRIS GL call `fogvertex()` set a mode and parameters affecting that mode. In OpenGL, you call `glFog()` once to set the mode, then again twice or more to set various parameters.

- Depth cueing is no longer a separate feature. Use linear fog instead of depth cueing. (This section provides an example of how to do this.) The following calls therefore have no direct OpenGL equivalent:

  - `depthcue()`

  - `lRGBrange()`

  - `lshaderange()`

  - `getdcm()`

- To adjust fog quality, call `glHint(GL_FOG_HINT)`.

Table 3-25 lists the IRIS GL calls for managing fog along with the corresponding OpenGL calls.

Table 3-25. Calls for Managing Fog

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
fogvertex() | glFog() | Set various fog parameters.
fogvertex(FG_ON) | glEnable(GL_FOG) | Turn fog on.
fogvertex(FG_OFF) | glDisable(GL_FOG) | Turn fog off.
depthcue() | glFog(GL_FOG_MODE, GL_LINEAR) | Use linear fog for depth cueing.

Table 3-26 lists the arguments you can pass to `glFog()`.

Table 3-26. Fog Parameters

Fog Parameter | Meaning | Default
--- | --- | ---
GL_FOG_DENSITY | Fog density. | 1.0
GL_FOG_START | Near distance for linear fog. | 0.0
GL_FOG_END | Far distance for linear fog. | 1.0
GL_FOG_INDEX | Fog color index. | 0.0
GL_FOG_COLOR | Fog RGBA color. | (0, 0, 0, 0)
GL_FOG_MODE | Fog mode. | see Table 3-27

The OpenGL fog density argument differs from the IRIS GL fog density argument. They are related as follows:

- If fogMode is EXP2:

  openGLfogDensity = (IRISGLfogDensity) (sqrt( - log( 1 / 255 ) ))

- If fogMode is EXP:

  openGLfogDensity = (IRISGLfogDensity) (- log( 1 / 255 ) )

where

sqrt | Is the square root operation.
log | Is the natural logarithm.
IRISGLfogDensity | Is the IRIS GL fog density.
openGLfogDensity | Is the OpenGL fog density.

To switch between calculating fog in per-pixel mode and per-vertex mode, use `glHint(GL_FOG_HINT``,` hintMode`)`. Two hint modes are available:

GL_NICEST |  | per-pixel fog calculation
GL_FASTEST |  | per-vertex fog calculation

Table 3-27 lists the OpenGL equivalents for IRIS GL fog modes.

Table 3-27. Fog Modes

IRIS GL Fog Mode | OpenGL Fog Mode | Hint Mode | Meaning
--- | --- | --- | ---
FG_VTX_EXP, FG_PIX_EXP | GL_EXP | GL_FASTEST, GL_NICEST | Heavy fog mode (default)
FG_VTX_EXP2, FG_PIX_EXP2 | GL_EXP2 | GL_FASTEST, GL_NICEST | Haze mode
FG_VTX_LIN, FG_PIX_LIN | GL_LINEAR | GL_FASTEST, GL_NICEST | Linear fog mode (use for depthcueing)

Example 3-3 shows a code fragment that demonstrates depth cueing in OpenGL.

Example 3-3. Depth Cueing in OpenGL

    /*
     *  depthcue.c
     *  This program draws a wireframe model, which uses
     *  intensity (brightness) to give clues to distance.
     *  Fog is used to achieve this effect.
     */
    #include <stdlib.h>
    #include <GL/glut.h>

    /*  Initialize linear fog for depth cueing.
     */
    void myinit(void)
    {
        GLfloat fogColor[4] = {0.0, 0.0, 0.0, 1.0};

        glEnable(GL_FOG);
        glFogi(GL_FOG_MODE, GL_LINEAR);
        glHint(GL_FOG_HINT, GL_NICEST);  /*  per pixel   */
        glFogf(GL_FOG_START, 3.0);
        glFogf(GL_FOG_END, 5.0);
        glFogfv(GL_FOG_COLOR, fogColor);
        glClearColor(0.0, 0.0, 0.0, 1.0);

        glDepthFunc(GL_LESS);
        glEnable(GL_DEPTH_TEST);
        glShadeModel(GL_FLAT);
    }

    /*  display() draws an icosahedron.
     */
    void display(void)
    {
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glColor3f(1.0, 1.0, 1.0);
        glutWireIcosahedron();
        glFlush();
    }

    void myReshape(int w, int h)
    {
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 3.0, 5.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -4.0);  /*  move object into view   */
    }

    /*  Main Loop
     */
    int main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
        glutCreateWindow(argv[0]);
        myinit();
        glutReshapeFunc(myReshape);
        glutDisplayFunc(display);
        glutMainLoop();
        return 0;             /* ANSI C requires main to return int. */
    }

## Porting Curve and Surface Commands

OpenGL doesn't support equivalents to the old-style curves and surface patches. You have to reimplement your code if it uses any of these calls:

- `defbasis()`

- `curvebasis()`, `curveprecision()`, `crv()`, `crvn()`, `rcrv()`, `rcrvn()`, and `curveit()`

- `patchbasis()`, `patchcurves()`, `patchprecision()`, `patch()`, and `rpatch()`

Silicon Graphics recommends that you reimplement these calls using evaluators, rather than trying to replace them with NURBS. Refer to the OpenGL Reference Manual and to the section “Evaluators” on page 440 of the OpenGL Programming Guide, Second Edition, for more information on using evaluators.

### NURBS Objects

OpenGL treats NURBS as objects, similar to the way it treats quadrics: you create a NURBS object and then specify how it should be rendered. Table 3-28 lists the NURBS object commands.

Table 3-28. Calls for Managing NURBS Objects

OpenGL Call | Meaning
--- | ---
gluNewNurbsRenderer() | Create a new NURBS object.
gluDeleteNurbsRenderer() | Delete a NURBS object.
gluNurbsCallback() | Associate a callback for error handling with a NURBS object.

When using NURBS objects, consider the following issues:

- NURBS control points are now floats, not doubles.

- The stride parameter is now counted in floats, not bytes.

- If you're using lighting and you're not specifying normals, call `glEnable()` with GL_AUTO_NORMAL as the parameter to generate normals automatically.

### NURBS Curves

The OpenGL calls for drawing NURBS are similar to the IRIS GL calls. You specify knot sequences and control points using a `gluNurbsCurve()` call, which must be contained within a `glBeginCurve()`/`glEndCurve()` pair.

Table 3-29 summarizes the calls for drawing NURBS curves.

Table 3-29. Calls for Drawing NURBS Curves

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
bgncurve() | gluBeginCurve() | Begin a curve definition.
nurbscurve() | gluNurbsCurve() | Specify curve attributes.
endcurve() | gluEndCurve() | End a curve definition.

Position, texture, and color coordinates are associated by presenting each as a separate`gluNurbsCurve()` inside the begin/end pair. You can make no more than one call to `gluNurbsCurve()` for each piece of color, position, and texture data within a single `gluBeginCurve()`/`gluEndCurve()` pair. You must make exactly one call to describe the position of the curve (a GL_MAP1_VERTEX_3 or GL_MAP1_VERTEX_4 description). When you call `gluEndCurve()`, the curve will be tessellated into line segments and then rendered.

Table 3-30 lists NURBS curve types.

Table 3-30. NURBS Curve Types

IRIS GL Type | OpenGL Type | Meaning
--- | --- | ---
N_V3D | GL_MAP1_VERTEX_3 | Polynomial curve.
N_V3DR | GL_MAP1_VERTEX_4 | Rational curve.
— | GL_MAP1_TEXTURE_COORD_* | Control points are texture coordinates.
— | GL_MAP1_NORMAL | Control points are normals.

For more information on available evaluator types, see the `glMap1` reference page.

### Trimming Curves

OpenGL trimming curves are similar to IRIS GL trimming curves. Table 3-31 lists the calls for defining trimming curves.

Table 3-31. Calls for Drawing NURBS Trimming Curves

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
bgntrim() | gluBeginTrim() | Begin trimming curve definition.
pwlcurve() | gluPwlCurve() | Define a piecewise linear curve.
nurbscurve() | gluNurbsCurve() | Specify trimming curve attributes.
endtrim() | gluEndTrim() | End trimming curve definition.

### NURBS Surfaces

Table 3-32 summarizes the calls for drawing NURBS surfaces.

Table 3-32. Calls for Drawing NURBS Surfaces

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
bgnsurface() | gluBeginSurface() | Begin a surface definition.
nurbssurface() | gluNurbsSurface() | Specify surface attributes.
endsurface() | gluEndSurface() | End a surface definition.

Table 3-33 lists parameters for surface types.

Table 3-33. NURBS Surface Types

IRIS GL Type | OpenGL Type | Meaning
--- | --- | ---
N_V3D | GL_MAP2_VERTEX_3 | Polynomial curve
N_V3DR | GL_MAP2_VERTEX_4 | Rational curve
N_C4D | GL_MAP2_COLOR_4 | Control points define color surface in (R,G,B,A) form
N_C4DR | — | —
N_T2D | GL_MAP2_TEXTURE_COORD_2 | Control points are texture coordinates.
N_T2DR | GL_MAP2_TEXTURE_COORD_3 | Control points are texture coordinates.
— | GL_MAP2_NORMAL | Control points are normals.

For more information on available evaluator types, see the `glMap2` reference page.

Example 3-4 draws a trimmed NURBS surface.

Example 3-4. Drawing an OpenGL NURBS surface

    /*
     *  trim.c
     *  This program draws a NURBS surface in the shape of a
     *  symmetrical hill, using both a NURBS curve and pwl
     *  (piecewise linear) curve to trim part of the surface.
     */
    #include <stdlib.h>
    #include <GL/glut.h>
    #include <stdio.h>

    GLfloat ctlpoints[4][4][3];

    GLUnurbsObj *theNurb;

    /*
     *  Initializes the control points of the surface to a small hill.
     *  The control points range from -3 to +3 in x, y, and z
     */
    void init_surface(void)
    {
       int u, v;

       for (u = 0; u < 4; u++) {
          for (v = 0; v < 4; v++) {
             ctlpoints[u][v][0] = 2.0 * ((GLfloat)u - 1.5);
             ctlpoints[u][v][1] = 2.0 * ((GLfloat)v - 1.5);

             if ((u == 1 || u == 2) && (v == 1 || v == 2))
                ctlpoints[u][v][2] = 3.0;
             else
                ctlpoints[u][v][2] = -3.0;
          }
       }
    }

    void nurbsError(GLenum errorCode)
    {
       const GLubyte *estring;

       estring = gluErrorString(errorCode);
       fprintf (stderr, "Nurbs Error: %s\n", estring);
       exit (0);
    }

    /*  Initialize material property and depth buffer.
     */
    void init(void)
    {
       GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
       GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
       GLfloat mat_shininess[] = { 100.0 };

       glClearColor(0.0, 0.0, 0.0, 0.0);
       glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
       glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
       glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

       glEnable(GL_LIGHTING);
       glEnable(GL_LIGHT0);
       glEnable(GL_DEPTH_TEST);
       glEnable(GL_AUTO_NORMAL);
       glEnable(GL_NORMALIZE);

       init_surface();

       theNurb = gluNewNurbsRenderer();
       gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
       gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
       gluNurbsCallback(theNurb, GLU_ERROR, (GLvoid (CALLBACK*)())nurbsError);
    }

    void display(void)
    {
       GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
       GLfloat edgePt[5][2] = /* counter clockwise */
          {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}};
       GLfloat curvePt[4][2] = /* clockwise */
          {{0.25, 0.5}, {0.25, 0.75}, {0.75, 0.75}, {0.75, 0.5}};
       GLfloat curveKnots[8] =
          {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
       GLfloat pwlPt[4][2] = /* clockwise */
          {{0.75, 0.5}, {0.5, 0.25}, {0.25, 0.5}};

       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
       glPushMatrix();
       glRotatef(330.0, 1.,0.,0.);
       glScalef(0.5, 0.5, 0.5);

       gluBeginSurface(theNurb);
       gluNurbsSurface(theNurb, 8, knots, 8, knots,
                       4*3, 3, &ctlpoints[0][0][0],
                       4, 4, GL_MAP2_VERTEX_3);
       gluBeginTrim(theNurb);
          gluPwlCurve(theNurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2);
       gluEndTrim(theNurb);
       gluBeginTrim(theNurb);
          gluNurbsCurve(theNurb, 8, curveKnots, 2,
                        &curvePt[0][0], 4, GLU_MAP1_TRIM_2);
          gluPwlCurve(theNurb, 3, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2);
       gluEndTrim(theNurb);
       gluEndSurface(theNurb);

       glPopMatrix();
       glFlush();
    }

    void reshape(int w, int h)
    {
       glViewport(0, 0, (GLsizei)w, (GLsizei)h);
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
       gluPerspective(45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);

       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
       glTranslatef(0.0, 0.0, -5.0);
    }

    /* ARGSUSED1 */
    void keyboard(unsigned char key, int x, int y)
    {
       switch (key) {
          case 27:
             exit(0);
             break;
       }
    }

    /*  Main Loop
     */
    int main(int argc, char **argv)
    {
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
       glutInitWindowSize(500, 500);
       glutInitWindowPosition(100, 100);
       glutCreateWindow(argv[0]);
       init();
       glutReshapeFunc(reshape);
       glutDisplayFunc(display);
       glutKeyboardFunc(keyboard);
       glutMainLoop();
       return 0;
    }

## Porting Antialiasing Calls

This section discusses topics related to antialiasing:

- “Blending”

- “afunction() Test Functions”

- “Antialiasing Calls”

In OpenGL, subpixel mode is always on, so the IRIS GL call `subpixel(TRUE)` is not necessary and has no OpenGL equivalent.

### Blending

Blending is off by default. If you use _DA or _MDA blend functions, you have to allocate destination alpha bits when you choose a visual. You have to use X to choose the visual, so refer to Chapter 4.

| Tip: In IRIS GL, when drawing to both front and back buffers, blending is done by reading one of the buffers, blending with that color, and then writing the result to both buffers. In OpenGL, however, each buffer is read in turn, blended, and then written.

Table 3-34 lists IRIS GL and OpenGL blending calls.

Table 3-34. Blending Calls

IRIS GL | OpenGL | Meaning
--- | --- | ---
— | glEnable(GL_BLEND) | Turn on blending.
blendfunction() | glBlendFunc() | Specify a blend function.

The calls `glBlendFunc()` and `blendfunction()` are almost identical. Table 3-35 lists the OpenGL equivalents to the IRIS GL blend factors.

Table 3-35. Blending Factors

IRIS GL | OpenGL | Notes
--- | --- | ---
BF_ZERO | GL_ZERO |
BF_ONE | GL_ONE |
BF_SA | GL_SRC_ALPHA |
BF_MSA | GL_ONE_MINUS_SRC_ALPHA |
BF_DA | GL_DST_ALPHA |
BF_MDA | GL_ONE_MINUS_DST_ALPHA |
BF_SC | GL_SRC_COLOR |
BF_MSC | GL_ONE_MINUS_SRC_COLOR | Destination only
BF_DC | GL_DST_COLOR | Source only
BF_MDC | GL_ONE_MINUS_DST_COLOR | Source only
BF_MIN_SA_MDA | GL_SRC_ALPHA_SATURATE |

### afunction() Test Functions

Table 3-36 lists the available alpha test functions.

Table 3-36. Alpha Test Functions

afunction() | glAlphaFunc()
--- | ---
AF_NOTEQUAL | GL_NOTEQUAL
AF_ALWAYS | GL_ALWAYS
AF_NEVER | GL_NEVER
AF_LESS | GL_LESS
AF_EQUAL | GL_EQUAL
AF_LEQUAL | GL_LEQUAL
AF_GREATER | GL_GREATER
AF_GEQUAL | GL_GEQUAL

### Antialiasing Calls

OpenGL has direct equivalents to the IRIS GL antialiasing calls. Table 3-37 lists them.

Table 3-37. Calls to Draw Antialiased Primitives

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
pntsmooth() | glEnable(GL_POINT_SMOOTH) | Enable antialiasing of points.
linesmooth() | glEnable(GL_LINE_SMOOTH) | Enable antialiasing of lines.
polysmooth() | glEnable(GL_POLYGON_SMOOTH) | Enable antialiasing of polygons.

Use the corresponding `glDisable()` calls to turn off antialiasing.

In IRIS GL, you can control the quality of the antialiasing by calling

    linesmooth(SML_ON + SML_SMOOTHER);

OpenGL provides similar control—use `glHint()`:

    glHint(GL_POINT_SMOOTH_HINT, hintMode);
    glHint(GL_LINE_SMOOTH_HINT, hintMode);
    glHint(GL_POLYGON_SMOOTH_HINT, hintMode);

hintMode is one of the following:

GL_NICEST | Use the highest quality smoothing.
GL_FASTEST | Use the most efficient smoothing.
GL_DONT_CARE | You don't care which smoothing method is used.

You could perform end correction in IRIS GL by calling

    linesmooth(SML_ON + SML_END_CORRECT);

OpenGL doesn't provide an equivalent for this call.

### Accumulation Buffer Calls

You must allocate your accumulation buffer by requesting the appropriate visual with `glXChooseVisual()`. For information on `glXChooseVisual()`, see the glXIntro and `glXChooseVisual` reference pages and refer to Chapter 4.

IRIS GL allows you to draw colors in the depth buffer, so `acbuf()` can use that buffer as a color source for accumulation. Some developers have used this depth-buffer reading capability to put depth data into accumulation buffers as well. OpenGL, on the other hand, doesn't put color information in the depth buffer; `glAccum()` thus can't read any information from the depth buffer.

To emulate accumulation from the depth buffer (using a configuration that supports auxiliary buffers) use the following procedure:

1. Use `glReadPixels()` to read from the depth buffer.

2. Massage the results as necessary.

3. Draw the resulting data to an auxiliary buffer.

4. Select this auxiliary buffer with `glReadBuffer()`, and use `glAccum()` to accumulate from that buffer.

This procedure requires caution in converting among data types.

Except as noted above, porting accumulation buffer calls is straightforward. Table 3-38 lists calls that affect the accumulation buffer.

Table 3-38. Accumulation Buffer Calls

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
acbuf() | glAccum() | Operate on the accumulation buffer.
— | glClearAccum() | Set clear values for accumulation buffer.
acbuf(AC_CLEAR) | glClear(GL_ACCUM_BUFFER_BIT) | Clear the accumulation buffer.
acsize() | glXChooseVisual() | Specify number of bitplanes per color component in accumulation buffer.

Table 3-39 lists the IRIS GL `acbuf()` arguments along with the corresponding arguments to the OpenGL `glAccum()` call.

Table 3-39. Accumulation Buffer Operations

IRIS GL Argument | OpenGL Argument
--- | ---
AC_ACCUMULATE | GL_ACCUM
AC_CLEAR_ACCUMULATE | GL_LOAD
AC_RETURN | GL_RETURN
AC_MULT | GL_MULT
AC_ADD | GL_ADD

### Stencil Plane Calls

In OpenGL, you allocate stencil planes by requesting the appropriate visual with `glXChooseVisual()`. (For information on `glXChooseVisual()`, see the glXIntro and `glXChooseVisual` reference pages and refer to Chapter 4.) Otherwise, porting should be straightforward. Table 3-40 lists calls that affect the stencil planes.

Table 3-40. Stencil Operations

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
stensize() | glXChooseVisual() | —
stencil(TRUE, ...) | glEnable(GL_STENCIL_TEST) | Enable stencil tests.
stencil() | glStencilOp() | Set stencil test actions.
stencil(... func, ...) | glStencilFunc() | Set function & reference value for stencil testing.
swritemask() | glStencilMask() | Specify which stencil bits can be written.
— | glClearStencil() | Specify the clear value for the stencil buffer.
sclear() | glClear(GL_STENCIL_BUFFER_BIT) | —

Stencil comparison functions and stencil pass/fail operations are almost equivalent in OpenGL and IRIS GL. The IRIS GL stencil function flags are prefaced with SF, the OpenGL flags with GL. IRIS GL pass/fail operation flags are prefaced with ST, the OpenGL flags with GL. Compare the IRIS GL and OpenGL reference pages for further details.

## Porting Display Lists

The OpenGL implementation of display lists is similar to the IRIS GL implementation, with two exceptions: you can't edit display lists once you've created them and you can't call functions from within display lists.

Because you can't edit or call functions from within display lists, these IRIS GL commands have no equivalents in OpenGL:

- `editobj()`

- `objdelete()`, `objinsert()`, and `objreplace()`

- `maketag()`, `gentag()`, `istag()`, and `deltag()`

- `callfunc()`

In IRIS GL, you used the commands `makeobj()` and `closeobj()` to create display lists. In OpenGL, you use `glNewList()` and `glEndList()`. For details on using `glNewList()` (including a description of the two list modes and a list of commands that are not compiled into the display list but are executed immediately), see the `glNewList` reference page and the OpenGL Programming Guide.

Table 3-41 lists the IRIS GL display list commands with the corresponding OpenGL commands.

Table 3-41. Display List Commands

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
makeobj() | glNewList() | Create a new display list.
closeobj() | glEndList() | Signal end of display list.
callobj() | glCallList(), glCallLists() | Execute display list(s).
isobj() | glIsList() | Test for display list existence.
delobj() | glDeleteLists() | Delete contiguous group of display lists.
genobj() | glGenLists() | Generate the given number of contiguous empty display lists.
— | glListBase() | Get the display list base for glCallLists().

### Porting bbox2() Calls

The command `bbox2()` has no OpenGL equivalent. To port `bbox2()` calls, first create a new (OpenGL) display list that has everything that was in the corresponding IRIS GL display list except the `bbox2()` call. Then, in feedback mode, draw a rectangle the same size as the IRIS GL bounding box: if nothing comes back, the box was completely clipped and you shouldn't draw the display list.

### Achieving Edited Display List Behavior

Although you can't actually edit OpenGL display lists, you can get a similar result by nesting display lists, then destroying and creating new versions of the sublists. The following OpenGL code fragment illustrates how to do this:

    glNewList (1, GL_COMPILE);
        glIndexi (MY_RED);
    glEndList ();
        glNewList (2, GL_COMPILE);
        glScalef (1.2, 1.2, 1.0);
    glEndList ();

    glNewList (3, GL_COMPILE);
        glCallList (1);
        glCallList (2);
    glEndList ();
         .
         .
    glDeleteLists (1, 2);
    glNewList (1, GL_COMPILE);
        glIndexi (MY_CYAN);
    glEndList ();
    glNewList (2, GL_COMPILE);
        glScalef (0.5, 0.5, 1.0);
    glEndList ();

### Sample Implementation of a Display List

Example 3-5 defines three IRIS GL display lists. One display list refers to the others in its definition.

Example 3-5. IRIS GL Display Lists

    makeobj (10);                             /* 10 object   */
       cpack (0x0000FF);
       recti (164, 33, 364, 600);             /* hollow rectangle */
    closeobj ();

    makeobj (20);                             /*20 object--various things*/
       cpack (0xFFFF00);
       circi(0,0,25);                         /* draw an unfilled circle */
       rectfi (100, 100, 200, 200);           /* draw filled rect */
    closeobj ();

    makeobj (30);                             /* 30 -- THE MAIN OBJECT */
       callobj (10);
       cpack (0xFFFFFF);
       rectfi (400, 100, 500, 300);            /* draw filled rect */
       callobj (20);
    closeobj ();
                                        /* now draw by calling the lists */
    callobj(30);

Translated to OpenGL, the code from Example 3-5 might look Example 3-6.

Example 3-6. OpenGL Display Lists

    glNewList( 10, GL_COMPILE );
       glColor3f( 1, 0, 0 );
       glRecti( 164, 33, 364, 600 );
    glEndList();

    glNewList( 20, GL_COMPILE );
       glColor3f( 1, 1, 0 );              /* set color to YELLOW  */
       glPolygonMode(GL_BOTH, GL_LINE);   /* unfilled mode */
       glBegin(GL_POLYGON);           /*use polygon to approximate circle*/
          for(i=0;i<100;i++) {
             cosine = 25 * cos(i*2*PI/100.0);
             sine =   25 * sin(i*2*PI/100.0);
            glVertex2f(cosine,sine);
          }
       glEnd();

       glBegin(GL_QUADS);
          glColorf( 0, 1, 1 );                    /* set color to CYAN  */
          glVertex2i(100,100);
          glVertex2i(100,200);
          glVertex2i(200,200);
          glVertex2i(100,200);
       glEnd();
    glEndList();

    glNewList(30, GL_COMPILE);                     /* List #30 */
       glCallList( 10 );
          glColorf( 1, 1, 1 );                     /* set color to WHITE */
          glRecti(400, 100, 500, 300);
       glCallList( 20 );
    glEndList();

                                            /* execute the display lists */
    glCallList( 30 );

## Porting defs, binds, and sets: Replacing `Tables' of Stored Definitions

OpenGL doesn't have tables of stored definitions—you cannot define lighting models, materials, textures, line styles, or patterns as separate objects as you could in IRIS GL. Thus, there are no direct equivalents to these IRIS GL calls:

- `lmdef()` and `lmbind()`

- `tevdef()` and `tevbind()`

- `texdef()` and `texbind()`

- `deflinestyle()` and `setlinestyle()`

- `defpattern()` and `setpattern()`

However, you can use display lists to mimic the def/bind behavior. (It's often best to optimize by writing display lists that contain just a single material definition.)

For example, here is a material definition in IRIS GL:

    float mat[] = {
        AMBIENT, .1, .1, .1,
        DIFFUSE, 0, .369, .165,
        SPECULAR, .5, .5, .5,
        SHININESS, 10,
        LMNULL
    };
    lmdef(DEFMATERIAL, 1, 0, mat);
    lmbind(MATERIAL, 1);

In the following code fragment, the same material is defined in a display list, referred to by the list number in MYMATERIAL:

    #define MYMATERIAL 10
    /* you would probably use glGenLists() to get list numbers */
    GLfloat   mat_amb[] = {.1, .1, .1, 1.0};
    GLfloat   mat_dif[] = {0, .369, .165, 1.0};
    GLfloat   mat_spec[] = { .5, .5, .5, 1.0};

    glNewList( MYMATERIAL, GL_COMPILE );
        glMaterialfv( GL_FRONT, GL_AMBIENT, mat_amb);
        glMaterialfv( GL_FRONT, GL_DIFFUSE, mat_dif);
        glMaterialfv( GL_FRONT, GL_SPECULAR, mat_spec);
        glMateriali(  GL_FRONT, GL_SHININESS, 10);
    glEndList();

    glCallList( MYMATERIAL );

## Porting Lighting and Materials Calls

You probably have to port lighting and materials code explicitly, because the OpenGL calls differ substantially from the IRIS GL calls. The OpenGL API has separate calls for setting lights, light models, and materials.

When porting lighting and materials calls, consider the following issues:

- OpenGL has no table of stored definitions. It has no separate `lmdef()` and `lmbind()` calls. You can use display lists to mimic the def/bind behavior. See “Porting defs, binds, and sets: Replacing `Tables' of Stored Definitions” for an example. Using display lists can have the added benefit of improving your program's performance.

- Attenuation is now associated with each light source, rather than with the overall lighting model.

- Diffuse and specular components are separated out in OpenGL light sources.

- OpenGL light sources have an alpha component. When porting your code, it's best to set the alpha component to 1.0, indicating 100% fully opaque. That way, alpha values will be determined solely by the alpha component of your materials and the objects in your scene will look just as they did in IRIS GL.

- In IRIS GL, you could call `lmcolor()` between a call to `bgnprimitive()` and the corresponding `endprimitive()` call. In OpenGL, you can't call `glColorMaterial()` between a `glBegin()` and its corresponding `glEnd()`.

Table 3-42 lists IRIS GL lighting and materials commands and the corresponding OpenGL commands.

Table 3-42. Lighting and Materials Commands

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
lmdef(DEFLIGHT,...) | glLight() | Define a light source.
lmdef(DEFLMODEL, ...) | glLightModel() | Define a lighting model.
lmbind() | glEnable(GL_LIGHT i) | Enable light i.
lmbind() | glEnable(GL_LIGHTING) | Enable lighting.
— | glGetLight() | Get light source parameters.
lmdef(DEFMATERIAL, ...) | glMaterial() | Define a material.
lmcolor() | glColorMaterial() | Change effect of color commands while lighting is active.
— | glGetMaterial() | Get material parameters.

When the first argument for `lmbind()` is DEFMATERIAL, the equivalent command is `glMaterial()`. Table 3-43 lists the various materials parameters you can set.

Table 3-43. Material Definition Parameters

lmdef() index | glMaterial() parameter | Default | Meaning
--- | --- | --- | ---
ALPHA | GL_DIFFUSE[a] |  |
AMBIENT | GL_AMBIENT | (0.2, 0.2, 0.2, 1.0) | Ambient color
DIFFUSE | GL_DIFFUSE | (0.8, 0.8, 0.8, 1.0) | Diffuse color
SPECULAR | GL_SPECULAR[b] | (0.0, 0.0, 0.0, 1.0) | Specular color
EMISSION | GL_EMISSION | (0.0, 0.0, 0.0, 1.0) | Emissive color
SHININESS | GL_SHININESS | 0.0 | Specular exponent
— | GL_AMBIENT_AND_ DIFFUSE | (see above) | Equivalent to calling glMaterial() twice with same values
COLORINDEXES | GL_COLOR_INDEXES | — | Color indices for ambient, diffuse, and specular lighting
[a] The fourth value in the GL_DIFFUSE parameter specifies the alpha value. [b] In IRIS GL, if the specular exponent (i.e. SHININESS) is zero, then the specular component of the light is not added in. In OpenGL, the specular component is added in anyway.

When the first argument of `lmdef()` is DEFLMODEL, the equivalent OpenGL call is `glLightModel()`. The exception is the case when the first argument of `lmdef()` is DEFLMODEL, ATTENUATION—in this case, you have to replace `lmdef()` with several `glLight()` calls. Table 3-44 lists equivalent lighting model parameters.

Table 3-44. Lighting Model Parameters

lmdef() index | glLightModel() Parameter | Default | Meaning
--- | --- | --- | ---
AMBIENT | GL_LIGHT_MODEL_AMBIENT | (0.2, 0.2, 0.2, 1.0) | Ambient color of scene.
ATTENUATION | — | — | See glLight().
LOCALVIEWER | GL_LIGHT_MODEL_ LOCAL_VIEWER | GL_FALSE | Viewer local (TRUE) or infinite (FALSE).
TWOSIDE | GL_LIGHT_MODEL_TWO_SIDE | GL_FALSE | Use two-sided lighting when TRUE.

When the first argument of `lmdef()` is DEFLIGHT, the equivalent OpenGL call is `glLight()`. Table 3-45 lists equivalent lighting parameters.

Table 3-45. Light Parameters

lmdef() index | glLight() Parameter | Default | Meaning
--- | --- | --- | ---
AMBIENT | GL_AMBIENT | (0.0, 0.0, 0.0, 1.0) | Ambient intensity.
| GL_DIFFUSE | (1.0, 1.0, 1.0, 1.0) | Diffuse intensity.
| GL_SPECULAR | (1.0, 1.0, 1.0, 1.0) | Specular intensity.
LCOLOR |  |  |
POSITION | GL_POSITION | (0.0, 0.0, 1.0, 0.0) | Position of light.
SPOTDIRECTION | GL_SPOT_DIRECTION | (0, 0, -1) | Spot direction.
SPOTLIGHT | -- |  |
| GL_SPOT_EXPONENT | 0 | Intensity distribution.
| GL_SPOT_CUTOFF | 180 | Maximum spread angle of light source.
DEFLMODEL, ATTENUATION, ... | GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION | (1,0,0) | Attenuation factors.

Example 3-7 is an OpenGL code fragment that demonstrates some OpenGL lighting and material calls, including two-sided lighting.

Example 3-7. OpenGL Lighting and Material Calls

    /* Initialize lighting */
    void myinit(void)
    {
        GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
        GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
        GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    /*      light_position is NOT default value     */
        GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);

        glFrontFace (GL_CW);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glEnable(GL_AUTO_NORMAL);
        glEnable(GL_NORMALIZE);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
    }

    void display(void)
    {
        GLdouble eqn[4] = {1.0, 0.0, -1.0, 1.0};
        GLfloat mat_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
        GLfloat back_diffuse[] = { 0.8, 0.2, 0.8, 1.0 };

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glPushMatrix ();
        glClipPlane (GL_CLIP_PLANE0, eqn);  /*  slice objects   */
        glEnable (GL_CLIP_PLANE0);

        glPushMatrix ();
        glTranslatef (0.0, 2.0, 0.0);
        auxSolidTeapot(1.0);        /*  one-sided lighting  */
        glPopMatrix ();

            /*  two-sided lighting, but same material       */
        glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
        glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
                      mat_diffuse);
        glPushMatrix ();
        glTranslatef (0.0, 0.0, 0.0);
        auxSolidTeapot(1.0);
        glPopMatrix ();

            /*  two-sided lighting, two different materials */
        glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
        glMaterialfv (GL_BACK, GL_DIFFUSE, back_diffuse);
        glPushMatrix ();
        glTranslatef (0.0, -2.0, 0.0);
        auxSolidTeapot(1.0);
        glPopMatrix ();

        glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
        glDisable (GL_CLIP_PLANE0);
        glPopMatrix ();
        glFlush();
    }

## Porting Texture Calls

When porting texture calls, consider these issues:

- At times, a single IRIS GL texturing call has to be replaced with two or more OpenGL calls. For those cases, edit the `toogl` output to use more variables than it did before or restructure the program.

- Use `glEnable()` and `glDisable()` to turn texturing capabilities on and off. See the reference page for details.

- OpenGL doesn't automatically generate mipmaps for you—if you're using mipmaps, call `gluBuild2DMipmaps()` first.

- Texture size in OpenGL is more strictly regulated than in IRIS GL. An OpenGL texture must be

  2n + 2b

  where n is an integer and b is

  - 0, if there's no border

  - 1, if there's a border pixel (textures in OpenGL can have 1 pixel borders)

- OpenGL 1.0 keeps no tables of textures, just a single 1D texture and a single 2D texture. If you want to reuse your textures, put them in a display list, as described in “Porting defs, binds, and sets: Replacing `Tables' of Stored Definitions”.

- In OpenGL 1.1, you can use named textures. Use the functions `glBindTexture()`, `glGenTexture()`, and `glDeleteTextures()` to work with named texture object. You can also call `glPrioritizeTextures()` to have certain textures preferentially be assigned to texture memory, and `glAreTexturesResident()` to determine whether a named texture is currently in texture memory.

- In OpenGL 1.1, you can use the subtexture mechanism for more efficient texture loading.

- OpenGL 1.1 offers the proxy texture mechanism to let you test whether a texture will fit into texture memory on a certain system.

Table 3-46 lists the general OpenGL equivalents to IRIS GL texture calls.

Table 3-46. Texture Commands

IRIS GL Call | OpenGL Call | Meaning
--- | --- | ---
texdef2d() | glTexImage2D() glTexParameter() gluBuild2DMipmaps() | Specify a 2D texture image.
texbind() | glTexParameter() glTexImage2D() gluBuild2DMipmaps() | Select a texture function.
tevdef() | glTexEnv() | Define a texture mapping environment.
tevbind() | glTexEnv() | Select a texture environment.
— | glTexImage1D() |
t2*(), t3*(), t4*() | glTexCoord*() | Set the current texture coordinates.
texgen() | glTexGen() | Control generation of texture coordinates.
— | glGetTexParameter() | —
— | gluBuild1DMipmaps() | —
— | gluBuild2DMipmaps() | —
— | gluScaleImage() | Scale an image to arbitrary size.

The OpenGL Programming Guide describes in detail how textures work in OpenGL. Here are a few general tips:

- Remember to call `gluBuild2DMipmaps()` or `gluBuild1DMipmaps()` before trying to use mipmaps.

- Use `glTexParameter()` to specify wrapping and filters.

- Use `glTexEnv()` to set up texturing environment.

- Use`glTexImage2D()` or `glTexImage1D()` to load each image.

- Use `glEnable()` and `glDisable()` to turn texturing capabilities on and off.

See the reference page for each call for detailed information.

### Translating tevdef()

Here's an example of an IRIS GL texture environment definition that specifies the TV_DECAL texture environment option:

    float tevprops[] = {TV_DECAL, TV_NULL};

    tevdef(1, 0, tevprops);

Here's how you could translate that code to OpenGL:

    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

Table 3-47 lists the IRIS GL texture environment options and their OpenGL equivalents.

Table 3-47. Texture Environment Options

IRIS GL Option | OpenGL Option
--- | ---
TV_MODULATE | GL_MODULATE
TV_DECAL | GL_DECAL
TV_BLEND | GL_BLEND
TV_COLOR | GL_TEXTURE_ENV_COLOR
TV_ALPHA | no direct OpenGL equivalent
TV_COMPONENT_SELECT | no direct OpenGL equivalent

For more detailed information on how to use these options, see the `glTexEnv` reference page.

### Translating texdef()

Here's an example of an IRIS GL texture definition:

    float texprops[] = { TX_MINFILTER, TX_POINT,
                         TX_MAGFILTER, TX_POINT,
                         TX_WRAP_S, TX_REPEAT,
                         TX_WRAP_T, TX_REPEAT,
                         TX_NULL };
    texdef2d(1, 1, 6, 6, granite_texture, 7, texprops)

In the above code example, `texdef()` specifies the TX_POINT filter as both the magnification and the minification filter, and TX_REPEAT as the wrapping behavior. It also specifies the texture image, in this case an image called granite_texture.

In OpenGL, the image specification is handled by the `glTexImage*()` functions and property-setting is handled by `glTexParameter()`. To translate to OpenGL, you'd replace a `texdef()` call with a call to a `glTexImage*()` routine and one or more calls to `glTexParameter()`.

Here's an example of one way you could translate the IRIS GL code fragment above:

    GLfloat nearest [] = {GL_NEAREST};
    GLfloat repeat [] = {GL_REPEAT};
    glTexParameterfv( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,
                      nearest);
    glTexParameterfv( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER,
                      nearest);
    glTexParameterfv( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,
                      repeat);
    glTexParameterfv( GL_TEXTURE_1D, GL_TEXTURE_WRAP_T,
                      repeat);
    glTexImage1D(GL_TEXTURE_1D, 0, 1, 6, 0, GL_RGB,
                      GL_UNSIGNED_SHORT,granite_tex);

Table 3-48 lists the IRIS GL texture parameters with their OpenGL equivalents. For more detailed information on OpenGL texture parameters, see the `glTexParameter` reference page.

Table 3-48. IRIS GL and OpenGL Texture Parameters

texdef(... np, ...) Option | glTexParameter() Parameter Name
--- | ---
TX_MINFILTER | GL_TEXTURE_MIN_FILTER
TX_MAGFILTER | GL_TEXTURE_MAG_FILTER
TX_WRAP, TX_WRAP_S | GL_TEXTURE_WRAP_S
TX_WRAP, TX_WRAP_T | GL_TEXTURE_WRAP_T
— | GL_TEXTURE_BORDER_COLOR

Table 3-49 lists the possible values of the IRIS GL texture parameters along with their OpenGL equivalents. If you used special values available only on systems with RealityEngine™ graphics, you may have to wait for RealityEngine extensions to OpenGL before you can translate these values exactly (see “Porting RealityEngine Graphics Features” for further discussion). For more information on possible values of OpenGL texture parameters, see the `glTexParameter` reference page.

Table 3-49. Values for IRIS GL and OpenGL Texture Parameters

IRIS GL | OpenGL
--- | ---
TX_POINT | GL_NEAREST
TX_BILINEAR | GL_LINEAR
TX_MIPMAP_POINT | GL_NEAREST_MIPMAP_NEAREST
TX_MIPMAP_BILINEAR | GL_LINEAR_MIPMAP_NEAREST
TX_MIPMAP_LINEAR | GL_NEAREST_MIPMAP_LINEAR
TX_TRILINEAR | GL_LINEAR_MIPMAP_LINEAR

### Translating texgen()

The functionality of `texgen()` is replaced by `glTexGen()` almost entirely, though you have to call `glEnable()` and `glDisable()` to turn coordinate generation on and off. Table 3-50 lists the equivalents for texture coordinate names.

Table 3-50. Texture Coordinate Names

IRIS GL Texture Coordinate | OpenGL Texture Coordinate | glEnable() Argument
--- | --- | ---
TX_S | GL_S | GL_TEXTURE_GEN_S
TX_T | GL_T | GL_TEXTURE_GEN_T
TX_R | GL_R | GL_TEXTURE_GEN_R
TX_Q | GL_Q | GL_TEXTURE_GEN_Q

Table 3-51 lists texture generation mode and plane names.

Table 3-51. Texture Generation Modes and Planes

IRIS GL Texture Mode | OpenGL Texture Mode | Corresponding Plane Name
--- | --- | ---
TG_LINEAR | GL_OBJECT_LINEAR | GL_OBJECT_PLANE
TG_CONTOUR | GL_EYE_LINEAR | GL_EYE_PLANE
TG_SPHEREMAP | GL_SPHERE_MAP | —

With IRIS GL, you call `texgen()` twice: once to simultaneously set the mode and a plane equation, and once more to enable texture coordinate generation. In OpenGL, you make three calls: two to `glTexGen()` (once to set the mode, and again to set the plane equation), and one to `glEnable()`. For example, if you called `texgen()` like this:

    texgen(TX_S, TG_LINEAR, planeParams);
    texgen(TX_S, TG_ON, NULL);

the equivalent OpenGL code is:

    glTexGen(GL_S, GL_TEXTURE_GEN_MODE, modeName);
    glTexGen(GL_S, GL_OBJECT_PLANE, planeParams);
    glEnable(GL_TEXTURE_GEN_S);

## Porting Picking Calls

All the IRIS GL picking calls have OpenGL equivalents, with the exception of `clearhitcode()`. Table 3-52 lists the IRIS GL picking calls and their OpenGL counterparts.

Table 3-52. Calls for Picking

IRIS GL Call | OpenGL Call | Notes
--- | --- | ---
clearhitcode() | not supported | Clears global variable, hitcode.
pick(), select() | glRenderMode(GL_SELECT) | Switch to selection/picking mode.
endpick(), endselect() | glRenderMode(GL_RENDER) | Switch back to rendering mode.
picksize() | gluPickMatrix() |
— | glSelectBuffer() | Set the return array.
initnames() | glInitNames() | —
pushname(), popname() | glPushName(), glPopName() | —
loadname() | glLoadName() | —

For more information on picking, refer to the `gluPickMatrix` reference page and the OpenGL Programming Guide. You can find a complete example and additional explanation in “OpenGL Programming for the X Window System,” page 438-441. See “GLX and GLUT Documentation”.

## Porting Feedback Calls

Feedback under IRIS GL differed from machine to machine. OpenGL standardizes feedback, so you can now rely on consistent feedback from machine to machine, and from implementation to implementation. Table 3-53 lists IRIS GL and OpenGL feedback calls.

Table 3-53. Feedback Calls

IRIS GL Call | OpenGL Call | Notes
--- | --- | ---
feedback() | glRenderMode(GL_FEEDBACK) | Switch to feedback mode.
endfeedback() | glRenderMode(GL_RENDER) | Switch back to rendering mode.
— | glFeedbackBuffer() | —
passthrough() | glPassThrough() | Place a token marker in the feedback buffer.

For more information, see the reference pages or the OpenGL Programming Guide.

Example 3-8 demonstrates OpenGL feedback.

Example 3-8. Feedback in OpenGL

    /*
     * feedback.c
     * This program demonstrates use of OpenGL feedback.  First,
     * a lighting environment is set up and a few lines are drawn.
     * Then feedback mode is entered, and the same lines are
     * drawn.  The results in the feedback buffer are printed.
     */
    #include <GL/glut.h>
    #include <stdlib.h>
    #include <stdio.h>

    /*  Initialize lighting.
     */
    void init(void)
    {
       glEnable(GL_LIGHTING);
       glEnable(GL_LIGHT0);
    }

    /* Draw a few lines and two points, one of which will
     * be clipped.  If in feedback mode, a passthrough token
     * is issued between the each primitive.
     */
    void drawGeometry(GLenum mode)
    {
       glBegin(GL_LINE_STRIP);
       glNormal3f(0.0, 0.0, 1.0);
       glVertex3f(30.0, 30.0, 0.0);
       glVertex3f(50.0, 60.0, 0.0);
       glVertex3f(70.0, 40.0, 0.0);
       glEnd();
       if (mode == GL_FEEDBACK)
          glPassThrough(1.0);
       glBegin(GL_POINTS);
       glVertex3f(-100.0, -100.0, -100.0);  /*  will be clipped  */
       glEnd();
       if (mode == GL_FEEDBACK)
          glPassThrough(2.0);
       glBegin(GL_POINTS);
       glNormal3f(0.0, 0.0, 1.0);
       glVertex3f(50.0, 50.0, 0.0);
       glEnd();
    }

    /* Write contents of one vertex to stdout.
    */
    void print3DcolorVertex(GLint size, GLint *count, GLfloat *buffer)
    {
       int i;

       printf("  ");
       for (i = 0; i < 7; i++) {
          printf("%4.2f ", buffer[size-(*count)]);
          *count = *count - 1;
       }
       printf ("\n");
    }

    /*  Write contents of entire buffer. (Parse tokens!)
    */
    void printBuffer(GLint size, GLfloat *buffer)
    {
       GLint count;
       GLfloat token;

       count = size;
       while (count) {
          token = buffer[size-count];
          count--;
          if (token == GL_PASS_THROUGH_TOKEN) {
             printf("GL_PASS_THROUGH_TOKEN\n");
             printf("  %4.2f\n", buffer[size-count]);
             count--;
          } else if (token == GL_POINT_TOKEN) {
             printf("GL_POINT_TOKEN\n");
             print3DcolorVertex (size, &count, buffer);
          } else if (token == GL_LINE_TOKEN) {
             printf("GL_LINE_TOKEN\n");
             print3DcolorVertex(size, &count, buffer);
             print3DcolorVertex(size, &count, buffer);
          } else if (token == GL_LINE_RESET_TOKEN) {
             printf("GL_LINE_RESET_TOKEN\n");
             print3DcolorVertex(size, &count, buffer);
             print3DcolorVertex(size, &count, buffer);
          }
       }
    }

    void display(void)
    {
       GLfloat feedBuffer[1024];
       GLint size;

       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
       glOrtho(0.0, 100.0, 0.0, 100.0, 0.0, 1.0);

       glClearColor(0.0, 0.0, 0.0, 0.0);
       glClear(GL_COLOR_BUFFER_BIT);
       drawGeometry(GL_RENDER);

       glFeedbackBuffer(1024, GL_3D_COLOR, feedBuffer);
       glRenderMode(GL_FEEDBACK);
       drawGeometry(GL_FEEDBACK);

       size = glRenderMode(GL_RENDER);
       printBuffer(size, feedBuffer);
    }

    /* ARGSUSED1 */
    void keyboard(unsigned char key, int x, int y)
    {
       switch (key) {
          case 27:
             exit(0);
             break;
       }
    }

    int main(int argc, char **argv)
    {
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
       glutInitWindowSize(100, 100);
       glutInitWindowPosition(100, 100);
       glutCreateWindow(argv[0]);
       init();
       glutDisplayFunc(display);
       glutKeyboardFunc(keyboard);
       glutMainLoop();
       return 0;
    }

## Porting RealityEngine Graphics Features

Some IRIS GL features that were available only on systems with RealityEngine graphics are unavailable in OpenGL; though several of them are supported either by OpenGL 1.1 or by an extension.

Table 3-54 lists the IRIS GL RealityEngine calls and their OpenGL counterparts.

Table 3-54. RealityEngine Calls

IRIS GL Call | OpenGL Call | Notes
--- | --- | ---
blendcolor() | glBlendColorEXT() | Specify a color to blend.
convolve() | glConvolutionFilter2DEXT(), glSeparableFilter2DEXT(), glConvolutionParameterEXT(), glPixelTransfer() | Convolve an input image with a kernel image.
displacepolygon() | glPolygonOffsetEXT() (OpenGL 1.0) glPolygonOffset() (OpenGL 1.1) | Specify z displacement for rendered polygons.
fbsubtexload() | Not supported | Load part or all of a texture.
gethgram() | glGetHistogramEXT() | Get histogram data.
getminmax() | glGetMinmaxEXT() | Get minimum and maximum graphics values.
hgram() | glHistogramEXT(), glResetHistogramEXT() | Compute histogram of pixel-transfer information.
ilbuffer() | Not supported | Allocate space for temporary image-processing results.
ildraw() | Not supported | Select an ilbuffer to draw into.
istexloaded() | glAreTexturesResidentEXT (OpenGL 1.0) glAreTexturesResident (OpenGL 1.1) | Find out whether a given texture is resident in texture memory.
leftbuffer() | glDrawBuffer(GL_LEFT) | Enable left-buffer drawing.
minmax() | glMinmaxEXT() | Compute minimum and maximum pixel values.
monobuffer() | Superseded by selection of an appropriate GLX visual | Select monoscopic viewing.
msalpha() | glEnable( GL_SAMPLE_ALPHA_TO_MASK_SGIS), glEnable( GL_SAMPLE_ALPHA_TO_ONE_SGIS) | Specify treatment of alpha values during multisampling.
msmask() | glSampleMaskSGIS() | Specify a multisample mask.
mspattern() | glSamplePatternSGIS() | Specify a sample pattern for multisampling.
mssize() | glXChooseVisual() with attribute GLX_SAMPLE_BUFFERS_SGIS | Configure multisample buffer.
multisample() | glEnable(GL_MULTISAMPLE_SGIS) | Enable or disable multisampling.
pixelmap() | glPixelMap() | Define pixel transfer lookup tables.
pixeltransfer() | glPixelTransfer() | Set transfer modes.
readcomponent() | glReadPixels() gives partial support; some readcomponent() features aren't yet supported | Choose a component source.
rightbuffer() | glDrawBuffer(GL_RIGHT) | Enable drawing in right buffer.
stereobuffer() | Superseded by selection of an appropriate GLX visual. | Select stereoscopic viewing.
subtexload() | OpenGL 1.1 function glTexSubImage2D() gives partial support (the flags parameter to subtexload() isn't supported) | Load part or all of a texture.
texdef3d() | glTexImage3DEXT() | Convert 3D image into a texture.
tlutbind() | Not supported | Select a texture lookup table.
tlutdef() | Not supported | Define a texture lookup table.
zbsize() | Superseded by selection of an appropriate GLX visual | Specify number of bitplanes to use for the depth buffer.

Some RealityEngine features (mostly involving texturing) don't correspond to specific IRIS GL functions, and thus don't fit nicely into Table 3-54. Some such features are supported by extensions to OpenGL; you should check at runtime to see if the relevant extension is supported by calling `glGetString(GL_EXTENSIONS)` (see the `glGetString` reference page for more information). Some other non-function-specific IRIS GL RealityEngine features aren't supported at all.

Each of the following features is supported on a given machine if the corresponding OpenGL extension is supported. (“OpenGL Extensions” points you to additional information):

- The internal texture storage format (TX_INTERNAL_FORMAT in IRIS GL) is supported by the texture extension (GL_EXT_texture). OpenGL without extensions supports a superset of the formats previously specified by TX_EXTERNAL_FORMAT; see the `glTexImage2D` reference page for more information.

- Sharpen texture is supported by the GL_SGIS_sharpen_texture extension. This was done in IRIS GL by passing TX_SHARPEN to `texdef()`.

- Detail texture is supported by the GL_SGIS_detail_texture extension. This was done in IRIS GL by using the tokens TX_DETAIL, TX_ADD_DETAIL, and TX_MODULATE_DETAIL in `texdef()` calls.

- The detail texture and sharpen texture extension both support control points (pairs of level-of-detail and scale values) to control the rate at which the relevant filters are applied (see TX_CONTROL_CLAMP and TX_CONTROL_POINT in the `texdef()` reference page). However, unlike IRIS GL, OpenGL uses a separate set of control points for each of the two filters.

- The IRIS GL ABGR pixel format is supported by the GL_EXT_abgr extension.

- Texture and texture environment definition and binding (formerly done by using `texdef()`, `texbind()`, `tevdef()`, and `tevbind()`) are currently handled in OpenGL by creating a display list containing a `glTexImage2D()` call. (No OpenGL extension is required.)

- The texture object extension supports named textures and allows you to prioritize textures using `glPrioritizeTexturesEXT()`. This functionality is also part of OpenGL 1.1.

These features are not supported in OpenGL or its extensions:

- Automatic mipmap generation is supported in the GLU library by `gluBuild2DMipmaps()`, but you can't change the default filtering used to generate mipmap levels (see TX_MIPMAP_FILTER_KERNEL in the `texdef` reference page).

- Bicubic texture filtering (see the descriptions of TX_BICUBIC and TX_BICUBIC_FILTER in the `texdef` reference page).

- shadows (see the descriptions of TX_BILINEAR_LEQUAL and TX_BILINEAR_GEQUAL in the `texdef()` reference page, and of TV_ALPHA in the `tevdef()` reference page).

- Component selection (see TV_COMPONENT_SELECT in the `tevdef()` reference page).

- Texture definition from a live video stream (available in IRIS GL using the flags argument to `subtexload()`).

  On some platforms, the video source extension, SGIX_video_source, lets you source pixel data from a video stream to the OpenGL renderer. The video source extension is available only for system configurations that have direct hardware paths from the video hardware to the graphics accelerator. On other systems, you need to transfer video data to host memory and then call `glDrawPixels()` or `glTex{Sub}Image()` to transfer data to the framebuffer or to texture memory.

- Fast texture definition, as performed in IRIS GL with TX_FAST_DEFINE.

- Quadlinear mipmap filtering (see TX_MIPMAP_QUADLINEAR in the `texdef` reference page).

- Specifying separate alpha and non-alpha functions for texture magnification filtering (see TX_MAGFILTER_COLOR and TX_MAGFILTER_ALPHA in the `texdef` reference page).

## OpenGL Extensions

For information on extensions to OpenGL, see the `glintro` and `glxintro` reference pages, as well as the reference pages for individual functions. (For a partial list of extension-related functions, see “Porting RealityEngine Graphics Features.”)

The manual OpenGL on Silicon Graphics Systems discusses each extension and explains how to use it.

Prev | Table of Contents | Next
Chapter 2. Using the toogl Tool |  | Chapter 4. OpenGL in the X Window System