Sorry, I've not had much time so here's the code for the raytracer as it is.
type vec3d
x as double
y as double
z as double
end type
type sphere
union
coords as vec3d
type
x as double
y as double
z as double
end type
end union
radius as double
radius2 as double
radius_recip as double
min_dist as double
argb as uinteger
red as double
gre as double
blu as double
dif as double
ref as double
next_sphere as sphere ptr
end type
type world
first_sphere as sphere ptr
first_light as sphere ptr
current_sphere as sphere ptr
eye as vec3d
fac as double
red as double
gre as double
blu as double
ambient as double
end type
sub trace(byref world as world ptr,byval origin as vec3d,byval vec as vec3d)
dim as sphere ptr sphere=world->first_sphere,current_sphere
dim as double current_dist=100000,d
dim as double dist,dx,dy,dz,dtc,lx,ly,lz,s,spec,ca
'find closest hit
while sphere<>0
if sphere<>world->current_sphere then
dx=sphere->x-origin.x
dy=sphere->y-origin.y
dz=sphere->z-origin.z
dist=dx*vec.x+dy*vec.y+dz*vec.z
if dist>0.0 then
dx-=vec.x*dist
dy-=vec.y*dist
dz-=vec.z*dist
dtc=dx*dx+dy*dy+dz*dz
if dtc<=sphere->radius2 then
d=dist-sqr(sphere->radius2-dtc)
if (d>0)and(d<current_dist) then
current_sphere=sphere
current_dist=d
end if
end if
end if
end if
sphere=sphere->next_sphere
wend
dim as double vecx,vecy,vecz,sv
dim as double shadow
'if hit found then
if current_sphere<>0 then
origin.x+=current_dist*vec.x
origin.y+=current_dist*vec.y
origin.z+=current_dist*vec.z
vecx=world->first_light->x-origin.x
vecy=world->first_light->y-origin.y
vecz=world->first_light->z-origin.z
d=1.0/sqr(vecx*vecx+vecy*vecy+vecz*vecz)
vecx*=d
vecy*=d
vecz*=d
shadow=0
sphere=world->first_sphere
sv=1.0
'test for shadow
while (sphere<>0)'and(shadow=0)
if sphere<>current_sphere then
dx=sphere->x-origin.x
dy=sphere->y-origin.y
dz=sphere->z-origin.z
dist=dx*vecx+dy*vecy+dz*vecz
if dist>0.0 then
dx-=vecx*dist
dy-=vecy*dist
dz-=vecz*dist
dtc=dx*dx+dy*dy+dz*dz
if dtc<=sphere->radius2 then
shadow=sqr(dtc)/sphere->radius
if shadow<sv then sv=shadow
end if
end if
end if
sphere=sphere->next_sphere
wend
'shade
sv=sv*sv
dx=(origin.x-current_sphere->x)*current_sphere->radius_recip
dy=(origin.y-current_sphere->y)*current_sphere->radius_recip
dz=(origin.z-current_sphere->z)*current_sphere->radius_recip
ca=(dx*-vec.x+dy*-vec.y+dz*-vec.z)
if ca<0.0 then ca=0.0
lx=world->first_light->x-origin.x
ly=world->first_light->y-origin.y
lz=world->first_light->z-origin.z
d=2.0*(dx*vec.x+dy*vec.y+dz*vec.z)
vec.x-=dx*d
vec.y-=dy*d
vec.z-=dz*d
d=1.0/sqr(lx*lx+ly*ly+lz*lz)
s=((lx*dx+ly*dy+lz*dz)*d)*ca
spec=(lx*vec.x+ly*vec.y+lz*vec.z)*d
if s<0.0 then s=0.0
spec=(spec-0.8)*5.0
if spec<0.0 then spec=0.0
spec=spec*spec*spec*spec*spec*current_sphere->ref
world->red+=(current_sphere->red*s+spec)*world->fac*sv
world->gre+=(current_sphere->gre*s+spec)*world->fac*sv
world->blu+=(current_sphere->blu*s+spec)*world->fac*sv
world->fac*=current_sphere->ref
world->current_sphere=current_sphere
if world->fac>0.125 then trace(world,origin,vec)
end if
end sub
sub main
screenres 1360,768,32,1
dim as integer wwidth,height
screeninfo wwidth,height
dim as uinteger ptr buffer(0 to 1)
buffer(0)=callocate(len(uinteger)*wwidth*height)
buffer(1)=callocate(len(uinteger)*wwidth*height)
dim as world world
dim as sphere sphere1,sphere2,sphere3,sphere4,light
sphere1.radius=150
sphere1.radius2=sphere1.radius*sphere1.radius
sphere1.radius_recip=1.0/sphere1.radius
sphere1.x=210
sphere1.y=-180.0
sphere1.z=780.0
sphere1.ref=0.6
sphere1.red=rnd
sphere1.gre=rnd
sphere1.blu=rnd
sphere2.radius=150
sphere2.radius2=sphere2.radius*sphere2.radius
sphere2.radius_recip=1.0/sphere2.radius
sphere2.x=-20.0
sphere2.y=-60.0
sphere2.z=550.0
sphere2.ref=0.6
sphere2.red=rnd
sphere2.gre=rnd
sphere2.blu=rnd
sphere3.radius=150
sphere3.radius2=sphere3.radius*sphere3.radius
sphere3.radius_recip=1.0/sphere3.radius
sphere3.x=-180.0
sphere3.y=-60.0
sphere3.z=-1150.0
sphere3.ref=0.6
sphere3.red=rnd
sphere3.gre=rnd
sphere3.blu=rnd
sphere4.radius=10000
sphere4.radius2=sphere4.radius*sphere4.radius
sphere4.radius_recip=1.0/sphere4.radius
sphere4.x=2000.0
sphere4.y=500.0
sphere4.z=15000.0
sphere4.ref=0.0
sphere4.red=rnd*.25
sphere4.gre=rnd*.25
sphere4.blu=rnd*.25
dim as sphere floor(0 to 2000)
dim as integer sc
for x as integer=0 to 30 step 4
for y as integer=0 to 60 step 4
floor(sc).radius=20
floor(sc).radius2=floor(sc).radius*floor(sc).radius
floor(sc).radius_recip=1.0/floor(sc).radius
floor(sc).x=x*30-450
floor(sc).y=200.0+10.0*sin((x+1.0)/2)*cos(y/1.73)
floor(sc).z=y*40-800'+z_pos
floor(sc).ref=0.2
floor(sc).red=.6+rnd*.2
floor(sc).gre=.6+rnd*.2
floor(sc).blu=.2+rnd*.2
floor(sc).next_sphere=@floor(sc+1)
sc+=1
next
next
light.x=1500
light.y=-2000
light.z=-1000
dim as vec3d v,p
dim as double d,red,gre,blu
world.first_sphere=@sphere1
sphere1.next_sphere=@sphere2
sphere2.next_sphere=@sphere3
sphere3.next_sphere=@sphere4
sphere4.next_sphere=@floor(0)
world.first_light=@light
world.ambient=0.2
p.x=-40.0
p.y=0.0
p.z=-3000.0
dim as integer pix,q
for frame as integer=0 to 1
for y as double=-384 to 383
for x as double=-680 to 679
q+=1
if q=50 then
'sleep 1
q=0
end if
v.x=x-p.x
v.y=y-p.y
v.z=-p.z
d=1.0/sqr(v.x*v.x+v.y*v.y+v.z*v.z)
v.x*=d
v.y*=d
v.z*=d
world.red=0.0
world.gre=0.0
world.blu=0.0
world.fac=1.0
world.current_sphere=0
trace(@world,p,v)
if 1=2 then
v.x=x+0.5-p.x
v.y=y-p.y
v.z=-p.z
d=1.0/sqr(v.x*v.x+v.y*v.y+v.z*v.z)
v.x*=d
v.y*=d
v.z*=d
world.fac=1.0
world.current_sphere=0
trace(@world,p,v)
v.x=x-p.x
v.y=y+0.5-p.y
v.z=-p.z
d=1.0/sqr(v.x*v.x+v.y*v.y+v.z*v.z)
v.x*=d
v.y*=d
v.z*=d
world.fac=1.0
world.current_sphere=0
trace(@world,p,v)
v.x=x+0.5-p.x
v.y=y+0.5-p.y
v.z=-p.z
d=1.0/sqr(v.x*v.x+v.y*v.y+v.z*v.z)
v.x*=d
v.y*=d
v.z*=d
world.fac=1.0
world.current_sphere=0
trace(@world,p,v)
world.red*=0.25
world.gre*=0.25
world.blu*=0.25
endif
if world.red>1.0 then world.red=1.0
if world.gre>1.0 then world.gre=1.0
if world.blu>1.0 then world.blu=1.0
pset(x+680,y+384),((world.red*255.0)shl 16)or((world.gre*255.0)shl 8)or(world.blu*255.0)
pix=(x+(wwidth shr 1))+(y+(height shr 1))*wwidth
*(buffer(frame)+pix)=((world.red*255.0)shl 16)or((world.gre*255.0)shl 8)or(world.blu*255.0)
next
sleep 1
next
p.x=-p.x
'p.y=0.0
'p.z=-1400.0
next
dim as uinteger argb0,argb1,red0,gre0
for y as integer=0 to height-1
for x as integer=0 to wwidth-1
argb0=*(buffer(0)+x+y*wwidth)
argb1=*(buffer(1)+x+y*wwidth)
argb1=((argb1 and &hff)*178)+(((argb1 shr 8) and &hff)*39)+(((argb1 shr 16) and &hff)*39)
red0=217*((argb0 shr 16)and &hff)+39*(argb0 and &hff)
gre0=217*((argb0 shr 8)and &hff)+39*(argb0 and &hff)
pset(x,y),(argb1 shr 8) or ((red0 shl 8)and &hff0000) or (gre0 and &hff00)
next
next
end sub
main
sleep