io7m | single-page | multi-page | archive (zip, signature)
1. OverviewA Brief History Of Vertex Specification In OpenGL 3. Display Lists
PreviousUpNext

Immediate mode
Around the mid-1990s, 3D graphics hardware was appearing in consumer grade desktop PCs, workstations, and game consoles. OpenGL, at that time, appeared as a simple "immediate" API. The word "immediate" refers to the imperative nature of the API where the user programs a sequence of translation, rotation, and drawing commands. As an example, the user might call the following function once per frame to draw a triangle onscreen:
void
draw_triangle(void)
{
  glPushMatrix();
  glTranslated(20.0, 20.0, 0.0);
  glBegin(GL_TRIANGLES);
    glColor3d(1.0, 0.0, 0.0);
    glVertex3d(0.0, 0.0, 0.0);
    glColor3d(0.0, 1.0, 0.0);
    glVertex3d(1.0, 0.0, 0.0);
    glColor3d(0.0, 0.0, 1.0);
    glVertex3d(1.0, 1.0, 0.0);
  glEnd();
  glPopMatrix();
}
      
The above code would likely result in an image similar to the following:
The API modelled the graphics card as a large state machine with dozens of variables (such as "the current colour", modified with glColor3d()). It also required graphics hardware to implement multiple stacks of matrices to control projection, object orientation, object scaling, amongst other things.
As hardware evolved, it quickly became clear that the immediate mode model was hard to optimize for at the driver level. Programmers could submit vertex data and state changes in any arbitrary order and the drivers could make very few assumptions about the immutability of state at any given time. The immediate mode model was also grossly inefficient in terms of how vertex data was actually specified: real 3D mesh data requires much more than just simple vertex coordinates. A typical 3D mesh might require a colour value (glColor()), a normal vector (glNormal()), multiple texture coordinate values (glTexCoord()), fog coordinates (glFogCoord()), and more. This results in a huge number of function calls, even for relatively small models.
A complete example is as follows (source):
#include <assert.h>
#include <GL/glut.h>
#include <GL/glext.h>

static void
reshape(int width, int height)
{
  glViewport(0, 0, width, height);
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, width, 0, height, -1.0, 100.0);

  assert(glGetError() == GL_NO_ERROR);
}

static void
display(void)
{
  glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glPushMatrix();
  glTranslated(20.0, 20.0, 0.0);
  glBegin(GL_TRIANGLES);
    glColor3d(100.0, 0.0, 0.0);
    glVertex3d(0.0, 0.0, 0.0);
    glColor3d(0.0, 100.0, 0.0);
    glVertex3d(100.0, 0.0, 0.0);
    glColor3d(0.0, 0.0, 100.0);
    glVertex3d(100.0, 100.0, 0.0);
  glEnd();
  glPopMatrix();

  glutSwapBuffers();
}

int
main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutCreateWindow("Immediate mode triangle");
  glutReshapeFunc(reshape);
  glutDisplayFunc(display);
  glutIdleFunc(glutPostRedisplay);

  glutMainLoop();
  return 0;
}
      

PreviousUpNext
1. OverviewA Brief History Of Vertex Specification In OpenGL 3. Display Lists