Before moving forward with implementing a camera model, it would be good to have some sort of debugging tool. When writing a ray tracer, that tool is a rendered image.
Go has a built-in image package, that allows to easily create images, and save them as files on the disk.
Code for this post can be viewed here
The scene will be represented by a struct. Internally it will store the width and height of the desired image, as well as a pointer to an instance of image.RGBA.
In order to initialize the scene, we need to initialize the image.RGBA with the given dimensions. In Go this is done by creating an image.Rect struct and passing it to the image.NewRGBA function.
The whole code required to initialize the scene will be done in the NewScene function. The function should accept two integers as arguments, that represent the width and height of the image:
The assert library exposes some nifty helper functions, like ObjectsAreEqualValues, which does a deep equality check of an object’s values.
In order to test the following functions, I needed to write two helper functions to generate a new image.RGBA and fill the image with a random color:
I use these helpers to generate expected image.RGBA objects for ObjectsAreEqualValues.
For each pixel of the image, I want to set a specific color. This can be done simply enough by a double for loop, but we can expose a convenience function on Scene, called EachPixel. Go allows us to specify functions as arguments for other functions. We will leverage this fact by requiring a single argument in EachPixel — a function with the following signature func(int, int) color.RGBA. The two int values are the x and y coordinates of the image (which will be used later on for calculating a pixel in the image plane). The full implementation of the EachPixel function looks like this:
The setPixel function is just an adapter for Go’s built-in image.RGBA.Set.
Finally I want to save the image to a PNG file. As one might suspect, Go provides such a function in the image/png package, called png.Encode. Again, I’ve built an adapter for this function, that takes a filename, under which it should save the image.
Several interesting things happen in this code:
Here’s a simple main function that fills the image with values based on the current pixel:
This code produces the following image:
That’s all regarding creating and saving images in Go. Next up, a basic camera model, stay tuned.