110 lines
2.5 KiB
ObjectPascal
110 lines
2.5 KiB
ObjectPascal
{ Raytracer for a scene with a pair of spheres and multiple reflections }
|
|
program RtPair;
|
|
const MaxX = 639;
|
|
MaxY = 399;
|
|
HalfX = 320;
|
|
HalfY = 200;
|
|
|
|
var
|
|
gd, gm: Integer;
|
|
N, M: Integer;
|
|
X, Y, Z: Real;
|
|
U, V, W: Real;
|
|
I, E, F, P, D, T, R, G: Real;
|
|
stopReflection: Boolean;
|
|
C: Integer;
|
|
|
|
function Sign(x: Real): Real;
|
|
begin
|
|
if x>0 then
|
|
Sign := 1
|
|
else
|
|
Sign := -1;
|
|
end;
|
|
|
|
|
|
begin
|
|
InitGraphics;
|
|
SetPalette(0, $000);
|
|
SetPalette(4, $A00);
|
|
SetPalette(11, $0FF);
|
|
SetPalette(15, $FFF);
|
|
|
|
for N:=0 to MaxY do
|
|
for M:=0 to MaxX do
|
|
begin
|
|
{ Rays' origin point }
|
|
X := 0;
|
|
Y := -0.1;
|
|
Z := 3;
|
|
|
|
U := (M - 318) / HalfX;
|
|
V := (HalfY - N) / 321.34;
|
|
|
|
W := 1 / Sqrt(U*U + V*V + 1);
|
|
U := U*W;
|
|
V := V*W;
|
|
|
|
{ I is the horizontal direction of ray }
|
|
{ based on whether it is in left (U<0) or right (U>0) half of the screen }
|
|
I := Sign(U);
|
|
G := 1;
|
|
|
|
{ Start the reflection cycle. }
|
|
{ A ray may reflect between one sphere and another multiple times before hitting floor or sky. }
|
|
repeat
|
|
stopReflection := True;
|
|
E := X-I;
|
|
F := Y-I;
|
|
P := U*E + V*F - W*Z;
|
|
D := P*P - E*E - F*F - Z*Z + 1;
|
|
|
|
{ If ray reflects from a sphere one more time }
|
|
if D>0 then
|
|
begin
|
|
T := -P - Sqrt(D);
|
|
if T>0 then
|
|
begin
|
|
X := X + T*U;
|
|
Y := Y + T*V;
|
|
Z := Z - T*W;
|
|
E := X - I;
|
|
F := Y - I;
|
|
G := Z;
|
|
P := 2*(U*E + V*F - W*G);
|
|
U := U - P*E;
|
|
V := V - P*F;
|
|
W := W + P*G;
|
|
|
|
{ Invert ray's direction and continue the reflection cycle }
|
|
I := -I;
|
|
stopReflection := False;
|
|
end;
|
|
end;
|
|
until stopReflection;
|
|
|
|
{ If Y<0 (V<0) a ray hits the floor }
|
|
if V<0 then
|
|
begin
|
|
P := (Y+2)/V;
|
|
{ Select checkers floor with Black (0) and Red (4) tiles }
|
|
C := (1 And (Round(X - U*P) + Round(Z + W*P))) * 4;
|
|
end else begin
|
|
{ If Y>0 (V>0) a ray hits the sky }
|
|
{ Default sky color is Cyan (11) }
|
|
C := 11;
|
|
{ Condition for using color White (15) to create fancy Cyan-White horizon }
|
|
R := ArcTan(U/W);
|
|
R := 0.2+0.1*Cos(3*R)*Abs(Sin(5*R));
|
|
if Abs(G)<0.35 then
|
|
R := R + 1;
|
|
if V<R then
|
|
C := 15;
|
|
end;
|
|
|
|
{ Draw current pixel }
|
|
PutPixel(M, N, C);
|
|
end;
|
|
|
|
repeat until ConAvail;
|
|
end.
|