One of our chaps, Daniel A Nagy has written a short program to render ray-traced spheres above a checker board surface, but with the attribute clash that is prevalent on the ZX Spectrum this was in Monochrome only. Another chap, Paul Dunn has created a modern version of ZX Basic with additional keywords, etc. that runs on Windows and his environment doesn't suffer with colour clash, so he adapted the code to create a more colourful display.
I have taken this code and created a couple of versions of it for the BBC Micro. One for MODE 0 (still in monochrome) and the other for MODE 2 in 8 glorious colours. The upshot of this is that when run (albeit slowly) in an emulator in B/W mode it gives a quite passable greyscale rendered image. The coloured version isn't too bad either.
I thought I'd show the code here, include a disk image with the two programs on it, and include a few screenshots for your delight.
The beauty of the code is that the number of spheres can be adjusted along with their positions within the render, and the rendered image will reflect (no pun intended) the changes made. I'm yet to fully study and work out how this is done, but it does seem to be fairly simple.
In BeebEm it is possible to speed up by around 9x by selecting the 1 FPS option on the Speed menu, but even then you're looking at well over 10 minutes to draw the full screen.
I'm sure there could be tweaks made, and what about the possibility of writing this in machine code instead? Something way above my current skill set I would think. One option would be to utilise a second processor to see what sort of speed increases that would give. I don't have one at the moment so feel free to give it a go and report back your findings.
Here's the MODE 0 screen: First coloured MODE 2 screen: First MODE 2 screen in B/W: Second version in MODE 2 (better shadow contrast?): Second version in MODE 2 in B/W: Here's a copy of the code:
Code: Select all
5MODE2:VDU 23;8202;0;0;0;
10DATA 4,1,5,2,6,3
12FOR n%=1 TO 6:READ c%:VDU 19,n%,c%,0,0,0:NEXT n%
15DATA 0,6,1,7,5
17DIM cl%(5):FOR n%=1 TO 5:READ cl%(n%):NEXT n%
20s%=4:DIM c(s%,3):DIM r(s%):DIM q(s%)
30FOR k=1 TO s%:READ c(k,1),c(k,2),c(k,3),r:r(k)=r:q(k)=r*r:NEXT k
40DATA -0.8,-1,3.2,0.7
45DATA 0,-0.45,2,0.3
50DATA 1.2,-0.7,2.5,0.5
55DATA 0.4,-1,4,0.4
60FOR i=0 TO 1024 STEP 4:FOR j=0 TO 1280 STEP 8
70x=0.3:y=-0.5:z=0:ba%=3:dx=j-640:dy=512-i:dz=1300:dd=dx*dx+dy*dy+dz*dz
80GOSUB 100:NEXT j:NEXT i
90END
100n=(y>=0 OR dy<=0):IF NOT n THEN s=-y/dy
110FOR k=1 TO s%
120px=c(k,1)-x:py=c(k,2)-y:pz=c(k,3)-z
130pp=px*px+py*py+pz*pz
140sc=px*dx+py*dy+pz*dz
150IF sc<=0 THEN GOTO 200
160bb=sc*sc/dd
170aa=q(k)-pp+bb
180IF aa<=0 THEN GOTO 200
190sc=(SQR bb-SQR aa)/SQR dd:IF sc<s OR n<0 THEN n=k:s=sc
200NEXT k
210IF n<0 THEN GCOL 0,1+(dy*dy/dd)*7:PLOT 69,j,i:n=0:RETURN
220dx=dx*s:dy=dy*s:dz=dz*s:dd=dd*s*s
230x=x+dx:y=y+dy:z=z+dz
240IF n=0 THEN GOTO 300
250nx=x-c(n,1):ny=y-c(n,2):nz=z-c(n,3)
260nn=nx*nx+ny*ny+nz*nz
270l=2*(dx*nx+dy*ny+dz*nz)/nn
280dx=dx-nx*l:dy=dy-ny*l:dz=dz-nz*l
290GOTO 100
300FOR k=1 TO s%
310u=c(k,1)-x:v=c(k,3)-z: IF u*u+v*v<=q(k) THEN ba%=1
320NEXT k
330IF (x-INT x>.5)=(z-INT z>.5) THEN GCOL 0,cl%(ba%) ELSE GCOL 0,cl%(ba%+1)
335PLOT 69,j,i
340RETURN