Building a Graphics EngineAround the start of the fall semester, I suddenly became interested in computer graphics. I had a vague idea that objects were represented as triangular surfaces and that each triangle was projected onto a plane to determine which pixels to display. But I knew nothing about the geometry required for projection, or about textures and lighting. While looking for a resource that would help me learn these things as I built a graphics engine myself, I came across a YouTube tutorial that seemed perfect. It used no graphics libraries such as OpenGL; its only interface to the computer screen was a function that printed a character corresponding to an individual pixel at a specified position. The tutorial had four parts, covering everything from basic projective geometry to textures. It was exactly the guide I wanted, with one problem: the pixel-printing function belonged to the Windows console API and worked only on Windows. Since I use a MacBook, I needed to find a replacement. Xcode might have let me develop a console application with similar functionality, but with the semester about to begin, I wasn't up for digging into a new development tool. So I put the project on hold. This week, after the semester ended, I returned to the project. Sitting down to work on it again gave me a new goal: this time, I would build a graphics engine using only what I already knew, without consulting any outside resources. Understanding the principles mattered more to me than optimizing performance, so I chose Python, which would let me turn ideas into code quickly. To draw pixels, I could simply create and manipulate a two-dimensional array of characters large enough to fill the console, then print it. I got straight to coding. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from time import sleep, time class XY: def __init__( self , x, y): self .x = x self .y = y WIDTH, HEIGHT = 100 , 30 SCREEN_BASE = [[ ' ' for _ in range (WIDTH)] for _ in range (HEIGHT)] SCREEN = SCREEN_BASE.copy() def clear(): SCREEN = SCREEN_BASE.copy() def fill(xy): SCREEN[HEIGHT - 1 - xy.y][xy.x] = '▇' def render(pixels): clear() for pixel in pixels: fill(pixel) output = ' ' .join( '' .join(col for col in row) for row in SCREEN) print (output) <div sty