I got sick of rewritting everything for lighting so I wrote a unit to save me time. For usage rights check the embedded readme/license/terms etc. It's a simple controller for the OpenGL lights and is quite versital. I'd like your critique.

This was written in Delphi 6 with the current DOT Toolkit.

[pascal]{
This unit was written by Robert Kosek. (C) December 2004, All rights reserved.
Use at your own risk/inconvenience. The author is not responsible for any
problems, instability, stress or weight gain caused by the use of this unit.

This unit, OOLights.pas, is freely usable in commercial/shareware applications
so long as the filename is unchanged and the Author (Robert Kosek) is credited.

Any modifications should be submitted to me via PM at the http://www.dgdev.tk
forums.

** TAKEN FROM THE REDBOOK CHAPTER 6 **
http://fly.cc.fer.hr/~unreal/theredbook/chapter06.html

Parameter Name Default Value Meaning
GL_AMBIENT (0.0, 0.0, 0.0, 1.0) ambient RGBA intensity of light
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) diffuse RGBA intensity of light
GL_SPECULAR (1.0, 1.0, 1.0, 1.0) specular RGBA intensity of light
GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) position of light
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) (x, y, z) direction of spotlight
GL_SPOT_EXPONENT 0.0 spotlight exponent
GL_SPOT_CUTOFF 180.0 spotlight cutoff angle
GL_CONSTANT_ATTENUATION 1.0 constant attenuation factor
GL_LINEAR_ATTENUATION 0.0 linear attenuation factor
GL_QUADRATIC_ATTENUATION 0.0 quadratic attenuation factor
}

unit OOLights;

interface

uses
Windows, SysUtils, Classes, GL, GLu, DotMath;

type
TLightItem = class(TCollectionItem)
private
FLightNumber: GLUint;
FAmbient,FDiffuse,FSpecular,FPosition: TDotVector4;
FSpotDirection: TDotVector3;
FSpotExponent: GLFloat;
FSpotCutOff: GLFloat;
FConstantAttenuation: GLfloat;
FLinearAttenuation: GLfloat;
FQuadraticAttenuation: GLfloat;
public
property LightNumber: GLUint read FLightNumber write FLightNumber;
property Ambient: TDotVector4 read FAmbient write FAmbient;
property Diffuse: TDotVector4 read FDiffuse write FDiffuse;
property Specular: TDotVector4 read FSpecular write FSpecular;
property Position: TDotVector4 read FPosition write FPosition;
property SpotDirection: TDotVector3 read FSpotDirection write FSpotDirection;
property SpotExponent: GLfloat read FSpotExponent write FSpotExponent;
property SpotCutOff: GLfloat read FSpotCutOff write FSpotCutOff;
property ConstantAttenuation: GLfloat read FConstantAttenuation write FConstantAttenuation;
property LinearAttenuation: GLfloat read FLinearAttenuation write FLinearAttenuation;
property QuadraticAttenuation: GLfloat read FQuadraticAttenuation write FQuadraticAttenuation;
constructor Create(Collection: TCollection); override;
procedure UpdateGL(visible: boolean);
end;

TLightSystem = class(TCollection)
private
function GetItem(Index: integer): TLightItem;
procedure SetItem(Index: integer; const Value: TLightItem);
public
property Items[Index: Integer]: TLightItem read GetItem write
SetItem; default;
constructor Create(ItemClass: TCollectionItemClass);
function AddNewLight: TLightItem;
end;

implementation

{ TLightSystem }

function TLightSystem.AddNewLight: TLightItem;
begin
if Count < 8 then
result := TLightItem.Create(Self)
else
result := nil;
end;

constructor TLightSystem.Create(ItemClass: TCollectionItemClass);
begin
inherited;
glEnable(GL_LIGHTING);
end;

function TLightSystem.GetItem(Index: Integer): TLightItem;
begin
Result := TLightItem(inherited GetItem(Index));
end;

procedure TLightSystem.SetItem(Index: Integer;
const Value: TLightItem);
begin
inherited SetItem(Index, Value);
end;

{ TLightItem }

{ tracks the lighting var and sets the default parameters }
constructor TLightItem.Create(Collection: TCollection);
const gll: array[0..7] of GLUInt = (
GL_LIGHT0,GL_LIGHT1,GL_LIGHT2,GL_LIGHT3,GL_LIGHT4,
GL_LIGHT5,GL_LIGHT6,GL_LIGHT7
);
begin
inherited Create(Collection);

if Collection.Count-1 > 7 then raise EInvalidOperation.CreateFmt('Cannot have more than 8 light definitions. Count: %d',[Collection.Count]);
FLightNumber := gll[Collection.Count-1];
glEnable(FLightNumber);

FAmbient := dotVector4(0.0,0.0,0.0,1.0);
FDiffuse := dotVector4(1.0,1.0,1.0,1.0);
FSpecular := dotVector4(1.0,1.0,1.0,1.0);
FPosition := dotVector4(0.0,0.0,0.0,0.0);

FSpotDirection := dotVector3(0.0,0.0,-1.0);

FSpotExponent := 0.0;
FSpotCutOff := 180.0;

FConstantAttenuation := 1.0;
FLinearAttenuation := 0.0;
FQuadraticAttenuation := 1.0;
end;

{ Updates the light's vars and show/hides should it be needed }
procedure TLightItem.UpdateGL(visible: boolean);
begin
if visible then begin
glEnable(FLightNumber);

glLightfv(FLightNumber, GL_AMBIENT, @FAmbient.xyzw);
glLightfv(FLightNumber, GL_DIFFUSE, @FDiffuse.xyzw);
glLightfv(FLightNumber, GL_SPECULAR, @FSpecular.xyzw);
glLightfv(FLightNumber, GL_POSITION, @FPosition.xyzw);
glLightfv(FLightNumber, GL_SPOT_DIRECTION, @FSpotDirection.xyz);
glLightf( FLightNumber, GL_SPOT_EXPONENT, FSpotExponent);
glLightf( FLightNumber, GL_SPOT_CUTOFF, FSpotCutOff);
glLightf( FLightNumber, GL_CONSTANT_ATTENUATION, FConstantAttenuation);
glLightf( FLightNumber, GL_LINEAR_ATTENUATION, FLinearAttenuation);
glLightf( FLightNumber, GL_QUADRATIC_ATTENUATION, FQuadraticAttenuation);

end else glDisable(FLightNumber);
end;

end.[/pascal]