Writing Your First Image
Introduction: From "Hello World" to "Hello Image"
In the previous lesson, you wrote your first C++ program that printed "Hello, Raytracer!" to the terminal. That simple program established the basic structure we'll use throughout this course and verified that your development environment works correctly. Now we're ready to take an exciting leap forward: instead of outputting text, we're going to generate actual visual images.
This transition from text to images is a pivotal moment in your ray tracing journey. Every ray tracer, no matter how sophisticated, ultimately does one thing: it produces image data. The stunning photorealistic renders you see in movies, the beautiful architectural visualizations, and the realistic reflections in modern games — they all start with the same fundamental task we're about to tackle: writing color values for each pixel in an image.
In this lesson, you'll learn how to represent images as grids of colored pixels and how to output them in a format called PPM (Portable Pixmap). We'll start with something deliberately simple: a solid red image. This might seem basic compared to the complex 3D scenes we'll eventually render, but it establishes the foundation for everything to come. Once you understand how to generate and output image data, adding ray tracing to calculate what colors those pixels should be becomes a natural next step.
By the end of this lesson, you'll have a program that generates a complete image file. You'll see your code produce visual output for the first time, and you'll understand the structure that every image-generating program follows. This is where your ray tracer truly begins.
Understanding Pixels and Color
Before we can generate images, we need to understand what images actually are at a fundamental level. When you look at a photograph on your screen or a frame from a movie, you're seeing a grid of tiny colored dots called pixels. The word "pixel" is short for "picture element," and it represents the smallest unit of an image that we can control individually.
Think of an image like a mosaic made of tiny colored tiles. Each tile is a single color, and when you step back and look at all the tiles together, they form a complete picture. Pixels work the same way. A typical image might be 1920 pixels wide and 1080 pixels tall, giving us over two million individual pixels. Each one contributes its small part to the overall image.
Every pixel has a color, and in computer graphics, we typically represent colors using the RGB color model. RGB stands for Red, Green, and Blue — the three primary colors of light. This might seem different from what you learned in art class, where the primary colors are red, yellow, and blue. That's because mixing paint (subtractive color) works differently from mixing light (additive color). When you combine red, green, and blue light in different proportions, you can create any color visible to the human eye.
Each color component in RGB has an intensity value that tells us how much of that color to include. In most image formats, including the one we'll use today, these intensity values range from 0 to 255. A value of 0 means none of that color, while 255 means the maximum amount. For example, pure red would be represented as red=255, green=0, blue=0. Pure white, which is all colors at maximum intensity, would be red=255, green=255, blue=255. Black, the absence of light, would be red=0, green=0, blue=0.
Let's look at some examples to make this concrete. If we want a bright yellow pixel, we'd combine maximum red (255) with maximum green (255) and no blue (0). Yellow is what you get when you mix red and green light. For a purple pixel, we might use red=128, green=0, blue=128 — equal amounts of red and blue at medium intensity. For a dark gray, we might use red=64, green=64, blue=64 — equal amounts of all three colors at low intensity.

The reason we use the range 0 to 255 is that it corresponds to 8 bits of data. A bit is the smallest unit of computer memory, holding either 0 or 1. Eight bits can represent 256 different values (2 to the power of 8), which we number from 0 to 255. This means each color component takes exactly one byte of memory, and a full RGB pixel takes three bytes. This is efficient for computers to work with and provides enough precision that the human eye can't distinguish individual color steps.
When we create an image, we need to specify its dimensions: how many pixels wide and how many pixels tall. An image that's 256 pixels wide and 256 pixels tall contains 65,536 total pixels (256 × 256). We'll need to specify a color for each one of these pixels. The way we organize this data is as a two-dimensional grid, where we can refer to any pixel by its position. We typically use coordinates where the first number represents the horizontal position (column) and the second represents the vertical position (row).
