When people are doing programming exercises, a large number of them make 3D raytracers. While this is a really fun project with exciting results, it also results in people losing interest or typing code that they don’t necessarily understand.

While the end product doesn’t look as nice, I think people should start with 2D ray tracing before moving on to 3D. In this document, I will attempt to go through a simple computer program that can draw 2D shapes.

## Outputting an image

To make the implementation simpler, and to follow the raytracer convention, I will be outputting the image in the PPM format.

``````HEIGHT = 500
WIDTH = 500

print("P3")
print(f"{WIDTH} {HEIGHT}")
print("255")

for x in range(WIDTH):
for y in range(HEIGHT):
r, g, b = (100, 100, 200)
print(f"{r} {g} {b}", end=" ")
print()
``````

Running this code should result in a 500x500 image with a solid blue-ish colour. The whole point of this exercise will be deciding what to put in the RGB colour values in order to produce interesting results.

## Drawable objects

We will have a list of shapes that return whether a given `(x, y)` coordinate pair falls within it, and what colour it should be. Let’s create that list and replace put the call in our loop.

``````def solid_red(x, y):
if y > 150 or x > 150:
return (230, 100, 100)

shapes = [
solid_red,
]
shapes.reverse()

# ...

r, g, b = (0, 0, 0)

for drawable in shapes:
temp = drawable(x, y)
if temp:
r, g, b = temp
``````

Running this code should give you an image with a black square on the top left, and a red background.

## Drawing a square

``````def square(x, y, length, colour=(255, 255, 255)):
def inner(ix, iy):
if ix > x and iy > y and ix < x + length and iy < y + length:
return colour
return inner

def checkerboard(x, y):
if (x / 50) + (y / 50) % 2 == 0:
return (100, 100, 100)

shapes = [
checkerboard,
square(50, 50, 100)
]
``````