Here is my raytrace function that I made a while ago, it handles multiple lights fine (sometimes theres some shadows messed up, but I think thats the optimisations that I've done.) *EDIT* yea, I found that the BBIntersect function is not working like it should in the shadow detection routine. I've modified the code below.

BTW: a warning to anyone posting code, it was mangling my code when I posted it using the [ pascal ] tags (leaving out lines and whole segments of code), only after lots of trial and error did I figure out that the < and > signs were interfering with the HTML rendering, disable HTML in this post to fix it.

[pascal]
Function Tscene.Raytrace(Ray: TRay;TraceDepth: integer; var HitPrim, ChangeIndicator: Integer): vector;
Var I, J, TempHit, TempCh: integer;
Dist, TempD, Dott: single;
R: TRay;
Pos, N: Vector;
Shad, Diff, Spec: single;
Hit: boolean;
C, L: vector;
begin
Result := Makevector(0,0,0);
if TraceDepth > 5 then exit;

Dist := 1000000;
Hit := false;
HitPrim := -1;
ChangeIndicator := -1;
C := MakeVector(0,0,0);

if (LRI[Tracedepth].Lastprim > -1) and (Prim[LRI[TraceDepth].LastPrim].Intersect(Ray, Dist) <> 0) then
begin
Hit := true;
HitPrim := LRI[TraceDepth].LastPrim;
ChangeIndicator := HitPrim+1;
end;

For I := 0 to NumPrims-1 do
if I <> LRI[TraceDepth].LastPrim then
begin
if Prim[I].BBIntersect(Ray) then
if (Prim[I].Intersect(Ray, Dist) <> 0) then
begin
Hit := true;
HitPrim := I;
ChangeIndicator := I+1;
end;
end;

LRI[TraceDepth].LastPrim := HitPrim;

if Hit then
begin
R := TRay.Create;

Pos := VecAdd(Ray.Pos, VecMult(Ray.Dir, Dist));

for I := 0 to NumLights-1 do
begin


R.Dir := Normalise(VecSub(Light[I].Pos, Pos));
R.Pos := VecAdd(Pos, VecMult(R.Dir, 0.001));

Shad := 1;
TempD := Distance(VecSub(R.Pos, Light[I].Pos));



if (LRI[Tracedepth].LastShad[I] > -1) and (Prim[LRI[TraceDepth].LastShad[I]].Intersect(R, TempD) <> 0) then
begin
Shad := 0;
ChangeIndicator := ChangeIndicator + NumPrims;
end
else
for J := 0 to NumPrims-1 do
if J <> HitPrim then
begin
//if Prim[I].BBIntersect(R) then
if Prim[J].Intersect(R, TempD) <> 0 then
begin
Shad := 0;
ChangeIndicator := ChangeIndicator + NumPrims;
LRI[TraceDepth].LastShad[I] := J;
Break;
end;
end;

if Shad > 0 then
begin
N := Prim[HitPrim].GetNormal(Pos);
L := Normalise(VecSub(Light[I].Pos, Pos));

Dott := Dot(L, N); //Diffuse Shading
if Dott > 0 then
begin
Diff := Shad*Dott*Prim[HitPrim].Mat.DiffPower;
C := VecAdd(C, VecMult(VecMult(Light[I].Color, Prim[HitPrim].Mat.Diffuse), Diff));

end;

if Prim[HitPrim].Mat.Specular > 0 then //Specular Shading
begin
Dott := Dot(Ray.Dir, VecSub(L, VecMult(N, (Dot(L, N)* 2) )));
if (Dott > 0) then
begin
Spec := Power(Dott, 20) * Prim[HitPrim].Mat.Specular * Shad;
C := VecAdd(c, VecMult(Light[I].Color, Spec));
end;
end;
end;

end;


if Prim[HitPrim].Mat.Reflect > 0 then //Reflection
begin
// Tr := TRay.Create;

N := Prim[HitPrim].GetNormal(Pos);
R.Dir := VecSub(Ray.Dir, VecMult(N, 2*Dot(Ray.Dir, N)));
R.Pos := VecAdd(Pos, Vecmult(R.Dir, 0.01));


C := VecAdd(C,
VecMult(Raytrace(R, TraceDepth+1, TempHit, TempCh),
VecMult(Prim[HitPrim].Mat.Diffuse,Prim[HitPrim].Mat.Reflect)));

HitPrim := TempHit;
ChangeIndicator := ChangeIndicator+TempCh;
end;
end;

If C[0] > 1 then C[0] := 1;
If C[1] > 1 then C[1] := 1;
If C[2] > 1 then C[2] := 1;

// Blurry Reflections - Tr.Pos := R.Pos;
// Tr.Dir := R.Dir;
{ if TraceDepth = 0 then
begin
TempCol := Makevector(0,0,0);

For I := -1 to 1 do
for J := -1 to 1 do
begin
Tr.Dir[0] := I*0.01;
Tr.Dir[1] := J*0.01;
Tr.Dir[2] := 0;
Tr.Dir := VecAdd(Tr.Dir, R.Dir);

TempCol := VecAdd(RayTrace(TR, TraceDepth+1, TempHit, TempCh), TempCol);

end;
TempCol := VecMult(TempCol, 1/9);

C := VecAdd(C,
VecMult(TempCol, //Raytrace(R, TraceDepth+1, TempHit, TempCh),
VecMult(Mat[Prim[HitPrim].Mat].Diffuse,Mat[Prim[HitPrim].Mat].Reflect)));

end
else
begin
}
Result := C;
end;
[/pascal]