Skip to content

Instantly share code, notes, and snippets.

@binarycounter
Last active November 29, 2021 00:51
Show Gist options
  • Save binarycounter/008804b7da0bb6b1c604603368edb509 to your computer and use it in GitHub Desktop.
Save binarycounter/008804b7da0bb6b1c604603368edb509 to your computer and use it in GitHub Desktop.
A tiny simplistic python raytracer based on a BBC BASIC program https://twitter.com/bbcmicrobot/status/1464585083109707776
# An attempt to port this https://twitter.com/bbcmicrobot/status/1464585083109707776 from BBC Basic to python
# To understand how it works and maybe attempt to write something similar in 65816 assembly (SNES)
# License for my part of the code is MIT, cannot speak for the many people that worked on the original BBC BASIC version though.
# Requires the python modules PIL or Pillow for image output. Outputs a 8 bit monochrome PNG image.
from PIL import Image, ImageOps
import math
# Set up image
img=Image.new("L",(320,256))
# Pixel Plot loops
for pix_y in range(img.size[1]):
for pix_x in range(img.size[0]):
#Camera Position
X=0
Y=-0.1
Z=3
#Camera Rotation
U=(pix_x-(img.size[0]/2)-0.5)/(img.size[0]/2) # Replaced the hardcoded image dimensions with variables here so that the resolution can easily be changed
V=(pix_y-(img.size[1]/2)-0.5)/(img.size[0]/2)
W=1/math.sqrt(U*U+V*V+1)
#Perspective projection (?)
U=U*W
V=V*W
I = (-1,1)[U > 0] # Ternary operator replacing the "SGN" command
while(True): #Infinite loop with break and continue replacing GOTO
E=X-I
F=Y-I
P=U*E+V*F-W*Z
# Spheres (?)
D=P*P-E*E-F*F-Z*Z+1
if D>0:
T=-P-math.sqrt(D)
if T>0:
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
I=-I
continue
break
# Ground Checkerboard
if V<0:
P=(Y+2)/V
V=-V*((int(X-U*P)+int(Z-W*P) & 1)/2+.3)+.2
img.putpixel((pix_x,pix_y),int(255-V*255)) # Original has a backwards palette so i am inverting the pixels by subtracting them from the max brightness
img=ImageOps.flip(img) #Original plots from bottom, so image should be flipped
img.save("output.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment