Chapter 1
The First Steps

In an ideal world, only a few lines of code would produce graphics right now. Alas, in the 
real world, some preliminary housekeeping is necessary. In this chapter you will learn how 
to make the necessary connection between Windows and OpenGL. The plan is to produce 
some graphics as soon as possible, so be patient with the necessary setup. In the spirit of 
getting to the interesting code as soon as possible, this chapter is fairly short and ends with 
actual graphics output. Although it is just a simple colored background, it shows that the 
code setting it up successfully did its job. Though trivial, this simple scene is not just a token 
reward for enduring a necessary evil. The code for producing it forms the basis for more 
advanced output.
Directory Structure
To use this book effectively you will be writing code along the way and will create and save 
a number of projects, so pick a drive for keeping these OpenGL projects. Create a directory 
and name it OpenGL. Under that directory, create subdirectories named Chapter.1, 
Chapter.2, etc. Some chapters may produce several projects, and these each have their own 
subdirectories under the chapter directory. You can, of course, organize in some other way, 
but the book proceeds as if you use the recommended directory structure and names for 
your projects, so you must translate as you go.
Preliminary Code
Getting Ready to Start to Begin
OpenGL is intended to be fairly platform-independent, rather than just for Windows. 
Therefore, OpenGL needs a link to Windows, using some special 

PAGE 1
 structures and API extensions in Windows to provide this link. In Delphi a good place for 
the connection is within a form’s OnCreate event handler.
Create a new project and save it in a new directory under the OpenGL directory created 
earlier. Name the new directory Chapter.1, name the project First.Dpr, and name the main 
unit First1.Pas. Double-click the main form to set up the form’s OnCreate event handler. 
Define a variable of type TPixelFormatDescriptor and fill it in. Defining the pixel format with 
this structure permits describing some properties that the Windows GDI (graphical device 
interface) needs in order to work with OpenGL.

procedure TForm1.FormCreate(Sender: TObject);	
var	
  pfd: TPixelFormatDescriptor;	
  FormatIndex: integer;	
begin	
  fillchar(pfd,SizeOf(pfd),0);	
  with pfd do	
  begin	
    nSize      := SizeOf(pfd);	
    nVersion   := 1; {The current version of the descriptor is 1}	
    dwFlags    := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL;	
    iPixelType := PFD_TYPE_RGBA;	
    cColorBits := 24; {support 24-bit color}	
    cDepthBits := 32; {depth of z-buffer}	
    iLayerType := PFD_MAIN_PLANE;	
  end; {with}	
  FormatIndex := ChoosePixelFormat(Canvas.Handle,@pfd);	
end; {FormCreate}		
Inform the system of the desired properties by calling ChoosePixelFormat, passing it the 
form’s device context and a pointer to the descriptor. Depending on what the device context 
can support, the contents of the descriptor may be altered to reflect the best approximation 
of the request. Windows uses device contexts, and OpenGL uses rendering contexts. This code 
attempts to map them to each other.
Device Context
The use of a device context is not obvious in this code. In Delphi, the Canvas property is a 
wrapper for a window’s device context, and Canvas.Handle is the handle to the device 
context. This code uses native Delphi where possible, leaving out error checking and other 
details for clarity. Be patient for a while; the code improves later.

PAGE 2
 Descriptor Fields
This descriptor has a number of fields that can remain zero or the equivalent, so explicit 
assignment statements were unnecessary. Here is a quick look at the rest of the contents of 
the descriptor to meet the current needs:
? nSize. Windows structures often require the size of the structure as part of the structure 
itself. This field follows that tradition.
? nVersion. The version number of the descriptor structure is 1, so a 1 must be stored here.
? dwFlags. The bits are set by OR-ing together some predefined constants. 
PFD_DRAW_TO_WINDOW has an obvious meaning; you could be drawing to a bitmap in 
memory instead. PFD_SUPPORT_OPENGL is certainly a desired feature. Keep in mind that 
this code does not yet do anything with OpenGL; it just gets Windows ready for OpenGL. 
These are Windows structures and Windows API calls. Windows does not assume the code 
will work with OpenGL unless the code tells it to. ChoosePixelFormat attempts to find a 
pixel format with the same flags set as those passed to it in the descriptor.
? iPixelType. Use RGBA (red, green, blue, alpha) pixels. Explanation of Alpha comes later.
? cColorBits. Support 24-bit color.
? cDepthBits. Set the depth of the z-buffer to 32. Explanation of depth comes later.
? iLayerType. The current version only supports the main plane.
ChoosePixelFormat is a function that returns an integer, stored in FormatIndex. It returns 
zero to indicate an error or a positive number as an index to the appropriate pixel format. 
SetPixelFormat sets the pixel format of the device context, using that index. Now the bottom 
of the OnCreate event handler looks like this:

  FormatIndex := ChoosePixelFormat(Canvas.Handle,@pfd);	
  SetPixelFormat(Canvas.Handle,FormatIndex,@pfd);	
end; {FormCreate}	
The functions receive the handle to the window’s device context and change the pixel format 
of the window. So far none of the code produces visible results other than a standard blank 
form, but keep coding. OpenGL will shine forth soon.

PAGE 3
 Starting to Begin
Rendering Context
Now that the code takes care of the pixel format, proceed to the rendering context. Add 
GLContext to the private section of the form:

type	
  TForm1 = class(TForm)	
    procedure FormCreate(Sender: TObject);	
  private	
    GLContext  : HGLRC;	
  public	
    { Public declarations }	
  end;	
The HGLRC type is a handle to an OpenGL rendering context type. Here is its declaration 
for the interface unit:

type	
  HGLRC = THandle;	
The new variable receives the result of wglCreateContext. This is one of several wgl 
(Windows-GL) functions for managing rendering contexts. Place this call at the bottom of 
the event handler:

  FormatIndex := ChoosePixelFormat(Canvas.Handle,@pfd);	
  SetPixelFormat(Canvas.Handle,FormatIndex,@pfd);	
  GLContext := wglCreateContext(Canvas.Handle);	
end; {FormCreate}	
As the name implies, this function creates the OpenGL rendering context needed by the 
window. Now make it current:

  FormatIndex := ChoosePixelFormat(Canvas.Handle,@pfd);	
  SetPixelFormat(Canvas.Handle,FormatIndex,@pfd);	
  GLContext := wglCreateContext(Canvas.Handle);	
  wglMakeCurrent(Canvas.Handle,GLContext); 	
end; {FormCreate}	
Cleanup
You should always put away your tools when finished with them, and you should always 
put away Windows resources when finished with them. Go to the events page of the Object 
Inspector for the form. Double-click the OnDestroy event. Fill in the event handler as 
follows:

procedure TForm1.FormDestroy(Sender: TObject);	
begin	
  wglMakeCurrent(Canvas.Handle,0);	


PAGE 4
   wglDeleteContext(GLContext);	
end;	
Passing a zero to wglMakeCurrent makes the previously current context no longer current. 
Now that GLContext is no longer current, delete it with wglDeleteContext.
Begin
Uses Clause
So far the code is nothing but Windows and Delphi code. The time has arrived for some 
OpenGL code. Add OpenGL to a uses clause. Put it in the interface section in order to use an 
OpenGL type in the interface.

uses	
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,	
  Dialogs, OpenGL, Menus;	
Paint
Again go to the events page of the form’s Object Inspector. This time double-click the 
OnPaint event. This event fires every time the window (form) needs repainting, such as 
when the form has been partially (or fully) covered and then exposed again. It also fires 
when the form first shows. Make this event handler like the following:

procedure TForm1.FormPaint(Sender: TObject);	
begin	
  {background}	
  glClearColor(0.0,0.4,0.0,0.0);	
  glClear(GL_COLOR_BUFFER_BIT);	
	
  {error checking}	
  errorCode := glGetError;	
  if errorCode<>GL_NO_ERROR then	
    raise Exception.Create('Error in Paint'#13+	
      gluErrorString(errorCode));	
end;	
The given OpenGL commands have the following declaration:

procedure glClear(mask:GLbitfield); stdcall;	
procedure glClearColor(red,green,blue,alpha:GLclampf); stdcall;	
Their implementations are simply references to the DLL that contains the code and look like 
this:


PAGE 5
 procedure glClear; external opengl32;	
procedure glClearColor; external opengl32;	
Error Checking
Notice this code introduces a little bit of error checking. This method is small enough (so far) 
that including the error checking code at this point does not obscure the main activity.
Use glClearColor to set the background color. Each color component ranges in floating-point 
value from 0 to 1. In this case the color has no red, 0.4 units of green, and no blue. Set alpha 
to 0 for now. The background color is a dark green (a little less than half the maximum 
intensity of green, which would be 1.0).
This is a good time to introduce an OpenGL type. Much of this graphics library, including 
color specifications, uses floating-point numbers. To keep itself portable, OpenGL defines a 
type called GLfloat. Under Windows on Intel processors and compatibles, GLfloat is the 
same as a Delphi single, which is an IEEE (Institute for Electrical and Electronics Engineers) 
32-bit floating-point value. In the interface unit is a type declaration like this:

  GLfloat = single;	
Next call glClear and pass it a bit mask that tells it what to clear. This clears the buffers 
enabled for writing colors. For error checking this segment of code introduces the function 
glGetError, which appears often. It returns a number of type GLenum, which is an alias for 
cardinal. The following type declaration appears in the interface unit:

  GLenum = Cardinal;	
Store the result in errorCode, which you should add to the private section of the form 
declaration.

errorCode: GLenum;	
Compare the result to GL_NO_ERROR, a predefined constant of obvious meaning. If there is 
an error, raise an exception. The application handles this exception simply by displaying the 
message. The message includes another new function, gluErrorString, from the OpenGL 
utility library. It returns a pointer to some text (PChar). The text represents the meaning of 
the error number passed to the function. Delphi’s string concatenation knows how to handle 
that PChar.
The constant has this declaration:

  GL_NO_ERROR = 0;	

PAGE 6
 Here is the declaration for the function:

function gluErrorString(errCode:GLenum):PChar; stdcall;	
Since this function name begins with “glu,” its code is found in the other DLL:

function gluErrorString; external glu32;	
Now, save the program (you have been warned!) and compile it. Do not run it from the 
Delphi IDE (integrated development environment). OpenGL programs sometimes crash if 
launched from the IDE even though they work fine when run independently. That is why it 
was so important to save your work before starting, just in case you got stubborn and ran it 
from the IDE anyway. You might be lucky, but you might not. Use the Windows Run 
command, giving it the appropriate path. Behold! A dark green form!
More Device Context
Some of the code just written needs improving. The time has arrived to demonstrate why. 
Drag the form by its title bar left and right and up and down, so that parts are obscured and 
re-exposed repeatedly. Partially cover it with some other window, then uncover it. Do this a 
number of times until something strange happens. Eventually some part of the form fails to 
show green after exposure.
While Canvas.Handle is the handle to the device context, it is not reliable for these purposes, 
because it is generated on the fly when it is referenced and then released. So the device 
context matched up with the rendering context at one point may not even exist at another 
point. The rendering context would not then have a valid association. The application needs 
a handle it can control. In the private section of the form, define glDC:

type	
  TForm1 = class(TForm)	
    procedure FormCreate(Sender: TObject);	
    procedure FormDestroy(Sender: TObject);	
    procedure FormPaint(Sender: TObject);	
  private	
    GLContext: HGLRC;	
    glDC: HDC;	
    errorCode: GLenum;	
  public	
    { Public declarations }	
  end;	
In the FormCreate method (OnCreate handler), call getDC and replace all references to 
Canvas.Handle with glDC:


PAGE 7
   glDC := getDC(handle);	
  FormatIndex := ChoosePixelFormat(glDC,@pfd);	
  SetPixelFormat(glDC,FormatIndex,@pfd);	
  GLContext := wglCreateContext(glDC);	
  wglMakeCurrent(glDC,GLContext);	
end; {FormCreate}	
Also in the FormDestroy method (OnDestroy handler) replace Canvas.Handle with glDC:

procedure TForm1.FormDestroy (Sender: TObject);	
begin	
  wglMakeCurrent(glDC,0);	
  wglDeleteContext(GLContext);	
end;	
Save the code again, compile it, then run it (independently). Now it works much more 
reliably.
More Error Handling
In the FormCreate method is the basic setup required to use OpenGL under Windows. Now 
that the code has appeared in its simplicity, it is time to complicate it with error checking. It 
is not exciting, but all good software requires some kind of error handling or reporting. With 
these learning programs, if something fails, at least some kind of clue should appear. Add a 
Boolean to the form’s private declaration. As a field of a TObject descendant, it is initialized 
to false. If you are not familiar with this initialization, see Delphi’s online help for the 
InitInstance method under TObject.

  private	
    GLContext: HGLRC;	
    glDC: HDC;	
    errorCode: GLenum;	
    openGLReady: boolean;	
In the FormPaint method make a test of the value of OpenGLReady and exit if false. There is 
no point in calling OpenGL commands if they were not even set up.

procedure TForm1.FormPaint(Sender: TObject);	
begin	
  if not OpenGLReady then	
    exit;	
  {background}	
  glClearColor(0.0,0.4,0.0,0.0);	
  glClear(GL_COLOR_BUFFER_BIT);	
	
  {error checking}	


PAGE 8
   error := glGetError;	
  if error<>GL_NO_ERROR then	
    raise Exception.Create('Error in Paint'#13+	
      gluErrorString(errorCode));	
end;	
FormCreate also needs to test some function results. On failure, call GetLastError; this 
returns a Windows error code. If execution makes it all the way to the end of the method, the 
reward is setting OpenGLReady to true.

  glDC := getDC(handle);	
  FormatIndex := ChoosePixelFormat(glDC,@pfd);	
  if FormatIndex=0 then	
    raise Exception.Create('ChoosePixelFormat failed '+	
      IntToStr(GetLastError));	
	
  if not SetPixelFormat(glDC,FormatIndex,@pfd) then	
    raise Exception.Create('SetPixelFormat failed '+	
      IntToStr(GetLastError));	
	
  GLContext := wglCreateContext(glDC);	
  if GLContext=0 then	
    raise Exception.Create('wglCreateContext failed '+	
      IntToStr(GetLastError));	
	
  if not wglMakeCurrent(glDC,GLContext) then	
    raise Exception.Create('wglMakeCurrent failed '+	
      IntToStr(GetLastError));	
 	
  OpenGLReady := true;	
end; {FormCreate}	
In the FormDestroy method you need to shut down OpenGLReady so that any last-moment 
event messages do not cause code that is no longer valid to execute.

procedure TForm1.FormDestroy(Sender: TObject);	
begin	
  OpenGLReady := false;	
  wglMakeCurrent(glDC,0);	
  wglDeleteContext(GLContext);	
end;	
Be sure to save your work. The next chapter starts with this code as the foundation.


PAGE 9
 Identifier Reference
Identifier			Description
ChoosePixelFormat
A Windows function that receives a handle to a device context and a pointer to a pixel 
format descriptor. It returns an integer index to Windows’ best attempt at a pixel format 
matching the specifications in the descriptor.
getDC
A Windows function that receives a handle to a window and returns a handle to that 
window’s device context.
GetLastError
A Windows function that returns an integer representing the most recent error.
glClear
An OpenGL command that erases a buffer, filling it with the most recently specified 
background color. If the buffer is the color buffer, then the window is filled with the 
background color.
glClearColor
An OpenGL command that receives red, green, blue, and alpha floating-point values and 
sets the background color to be used by glClear.
GLenum
An OpenGL numeric type that maps to Delphi cardinal.
GLfloat
An OpenGL numeric type that maps to Delphi single.
glGetError
An OpenGL function that returns an integer value representing an error flag set by an 
OpenGL command, and clears that flag. If no error flags are set when called, the function 
returns the value of GL_NO_ERROR.
gluErrorString
An OpenGL utility function that receives an error number (such as returned by glGetError) 
and returns a pointer to a human-readable string (null-terminated) describing the associated 
OpenGL error flag.
GL_NO_ERROR
An OpenGL constant to represent a successful command.
HDC
A Windows type. Handle to a device context.

PAGE 10
 Identifier			Description
HGLRC
A Windows/OpenGL type. Handle to a rendering context.
SetPixelFormat
A Windows function that specifies the pixel format to use with the given device context. 
While ChoosePixelFormat merely obtains an index to a pixel format, this function sets that 
pixel format as the one to use. The function receives a handle to the device context, an index 
to the desired pixel format (such as the one returned by ChoosePixelFormat), and a pointer 
to the pixel format descriptor (as modified by ChoosePixelFormat). It returns true on success 
or false on failure. Call GetLastError to learn more about the failure.
TPixelFormatDescriptor
A Windows type. A structure of this type contains the fields needed to select and set a pixel 
format.
wglCreateContext
A Windows function that creates a rendering context for the specified device context. It 
receives a handle to the device context and returns a handle to the rendering context.
wglDeleteContext
A Windows function that deletes the specified rendering context. It receives the handle to 
the rendering context and returns true on success and false on failure.
wglMakeCurrent
A Windows function that makes the specified rendering context current (the one available 
for use) with the specified device context. It receives the handle to the device context and the 
handle to the rendering context and returns true on success and false on failure.


PAGE 11
 Summary
Chapter 1 showed how to:
? Link the Windows graphics device context with the OpenGL rendering context.
? Use actual OpenGL commands to fill a window with a color.
? Perform some basic error checking with OpenGL commands.
 
PAGE 12

