Working with Textures

Textures can do a lot to make your shapes more interesting to look at:

A screenshot from the WglTexture program that comes with these notes.

First you need to read in a texture and set up the environment for using textures. This is done in the InitGL method:

  CheckImage := ReadTexture('..\media\WaddelCreek.bmp', ImageWidth, ImageHeight);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, 3, ImageWidth,
  	ImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, CheckImage);

The call to ReadTexture is explained later in this document.

At the beginning of the paint or display method, you should prepare to use textures:

  glEnable(GL_TEXTURE_2D);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

At the end of the method, you should close texture mode:

  glDisable(GL_TEXTURE_2D);

Finally, when you actually draw the graphics to the screen, you should use should use the call glTextCoord before each call to an OpenGL function that defines a coordinate in a geometric shape:

  glBegin(GL_TRIANGLE_STRIP);
    glTexCoord2f(1.0, 1.0);  glVertex3f(-1, 0, 0);
    glTexCoord2f(1.0, 0.0);  glVertex3f(0, 1, 0);
    glTexCoord2f(0.0, 1.0);  glVertex3f(1, 0, 0);
    glTexCoord2f(0.0, 0.0);  glVertex3f(1, 0, 0);
  glEnd;

glTexCoord* is used, in effect, to tack the edges of your texture on to the faces of your geometric shape.

Loading a Texture

Here is a routine based on one by Jacobs in the Delphi Developers Guide to OpenGL book for reading in a texture:

{** This routine is based on a routine in the Jacobs OpenGL book. }
function TElfOpenGL.ReadTexture(const FilePath:string;var sWidth,tHeight: TGLsizei): Pointer;
type
  TRGB=packed record
    r,g,b: byte;
  end;
  TWrap=array[0..0] of TRGB;
const
  FileHeaderSize=SizeOf(TBitmapFileHeader);
  InfoHeaderSize=SizeOf(TBitmapInfoHeader);
var
  bmpfile: file;
  FileHeader: TBitmapFileHeader;
  InfoHeader: TBitmapInfoHeader;
  t: byte;
  x, Size: integer;
begin
  AssignFile(bmpfile,FilePath);
  Reset(bmpfile,1);
  Size := FileSize(bmpfile) - FileHeaderSize - InfoHeaderSize;
  blockread(bmpfile, FileHeader, FileHeaderSize);
  if FileHeader.bfType<>$4D42 then
    raise EInvalidGraphic.Create('Invalid Bitmap');
  blockread(bmpfile,InfoHeader,InfoHeaderSize);
  with InfoHeader do begin
    sWidth := biWidth;
    tHeight := biHeight;
  end;
  Getmem(result,size);
  Blockread(bmpfile,result^,size);
  for x := 0 to sWidth*tHeight-1 do
  // Convert from rgb to bgr
  with TWrap(result^)[x] do begin
    t := r;
    r := b;
    b := t;
  end;
end;