4.9 KiB
RaytracerGO
A raytracer and renderer writen in Go (Golang) following the book Raytracing in one weekend
Motivation
I've been meaning to tinker with graphics for quite a while and was motivated by a video programming a raytracing algorithm on a TI-84. Back in my school days I used to love to tinker with the TI-84 and also did some very elementary programming on it myself.
Video that started it all: Raytracing on a Graphing Calculator (again)
![TI-84 Raytracing](https://www.techeblog.com/wp-content/uploads/2022/12/ray-tracing-ti-84-plus-ce-graphing-calculator.jpg)
Why Go?
The story starts with Zig. A few colleagues of mine and I tried to work on a Guake-like browser using Zig. We chose Zig because it's C-like, modern and because their mascot is a lizard, of course. But I don't like Zig all that much, and right now Go has caught my attention.
I like the language a lot, it's still very C-like, doesn't have classes :), is open-source and resembles Python a lot, while still being fast and having crazy fast compiling speeds (which is something I've started to appreciate since dabbling with Linux From Scratch). The only draw back of Go is that it is a little bit slower than C++, but I just want to experience what the Python-version of C is like :)
![Go-Programming](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fprogramaenlinea.net%2Fwp-content%2Fuploads%2F2020%2F04%2Fgolang-1024x516.png&f=1&nofb=1&ipt=363a10979aa43c8925c481b76c8a2b03a50ce948b3548b40a29432caf8a534d1&ipo=images)
Taglibro
Chapter 1: The PPM-image format
![First PPM image](https://raytracing.github.io/images/img-1.01-first-ppm-image.png)
Yay this is the first image I've ever generated without using any external imported library ^^
Chapter 2: Vector operations: Ditching OOP for GO
Implemented the vec3 Class and colour utility functions without classes. Struktoj estas sufiĉa.
Chapter 3: Implementing the camera, rays and a background
To understand computer graphics better I will try to describe some important definitions with my own words:
- Rays: A ray is a 3D-vector with an origin pointing with some length in one direction (P(x)=O+x*b, where O is the origin and b is a vector pointing in one direction)
- Viewport: Is essentially a window (typically the user window) through which we see the 3D environment. Adjusting the viewport allows you to zoom in, pan around, or focus on specific areas of your scene.
- Camera: Is essentially a mathematical function (a virtual eye of sorts) that captures rays that originate from its position and pass through the viewport and generates an image that the user can see.
By the end of this chapter I generated the following background:
![Second PPM image](https://raytracing.github.io/images/img-1.02-blue-to-white.png)
Chapter 4: Creating a sphere
In this chapter I created a simple sphere and detect its surface by solving quadratic equations, which represent vectors. The sphere has no shading yet:
![Second PPM image](https://raytracing.github.io/images/img-1.03-red-sphere.png)
Chapter 5: Surface normals
The first part of the chapter was the calculation and visualization of the normals, which we need for shading. But I also implemented the fast inverse square algorithm in Go just like in Quake III, which is pretty clever and fast. I did primarily because 1) I'm working with 32-bit floats for the sake of memory efficiency and 2) I don't care about accuracy - also it's very educational. But as explained in this video the fast inverse square isn't always the better choice and in my case it probably isn't, because I need to import a Go standard library to disable data type safety and processor padding (something I've noticed when working with small data types in Zig). This is the first visualization of the normals of the sphere:
![Second PPM image](https://raytracing.github.io/images/img-1.04-normals-sphere.png)
The second part of the capter involved standardizing the code so that it can process multiple objects - it was quite translating this part into Go, as a lot of C++ OOP features are missing - but finally I managed to produce this neat output:
![Second PPM image](https://raytracing.github.io/images/img-1.05-normals-sphere-ground.png)
At the end I also added an intervals struct, to further simplify the code.
Chapter 6: The Camera struct
This chapter was yet another simplification of the existing code - the viewport and the camera were moved out of main and got their own struct. The camera struct and the render function have two tasks:
- Construct and dispatch rays into the world and
- Use the results of these rays to construct the rendered image