Skip to content
RuleOfSixPublic

About

A simple CPU-based image raytracer build from scratch in Rust that utilizes a 3D Projective Geometric Algebra (PGA) centric approach to rendering.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

26 Commits

Folders and files

Repository files navigation

A CPU Raytracer using Projective Geometric Algebra (PGA)

An example render using PGATracer

I have two main goals with this project:

  • To learn about 3D PGA and its graphical use cases
  • To get a deeper understanding of 3D image rendering

To that end, this is a simple software raytracer built from scratch without the use of any dependencies beyond the Rust standard library. For the raytracing part, I am using the tests from The Ray Tracer Challenge: A Test-Driven Guide by Jamis Buck, which is still a work in progress (I'm currently up to having implemented basic shadow rendering). Eventually, I'd like to extend it beyond the lengths of what that book covers, but this is my starting point.

The more interesting/unique aspect is the supporting 3D PGA library code. Projective Geometric Algebra is a particular Geometric Algebra with broad applicability in computer graphics. It represents planes as vectors, lines as bivectors, and points as trivectors, and includes the concept of lines/points "at infinity," along with a single "plane at infinity." It can encode any rotation or translation in the form of a rotor with 8 coefficients, as opposed to a 4x4 matrix with 16 coefficients. The core trouble in implementing it is often in how to encode the objects it deals with, as the only way to guarantee you can hold the result of any given operation (ie, any arbitrary multivector) is to use once again 16 coefficients, even though in reality the subset of these objects you are interested in will have at least half of them be zero. My solution was to use Rust's type system to separately handle each of the types my program would actually use separately, and utilize enums to allow room for methods which could return multiple of these primitives. In particular, after monomorphization and optimization the program should end up with a specialized function for the geometric product between any of two of these types. Many of the optimizations in how the library's data representations work rely on the assumption that you will only ever construct objects by taking the outer product of vectors - or in technical terms, that you will only ever be working with blades. Currently, the type system allows you to create non-blades, in part as the only target user of this library is myself, but I will likely rework it to disallow this in the future. Currently, my focus is on utilizing it in graphical applications and seeing how this differs from usual approaches; I find it interesting to have a software raytracer that does not use matrices anywhere in its source code.

On the topic of data representations, the multivector primitives use Rust's experimental portable SIMD data types. This was in part due to wanting practice working with parallel SIMD types, and in part due to wanting to offset the inefficiency of doing graphics calculations on the CPU. Using these types essentially forces me to work with the coefficients in a way that is conducive to compiler SIMD optimizations As a result, if you compile with the target-cpu=native flag you may see slight performance improvements.

I haven't done extensive performance tests yet, as the PGA code is not intended for use outside this project, so the implementations are very naive (especially as I went into this project initially quite blind). There are certainly many improvements to be made; I may start fine-tuning things more as I get further into the applications of the project and can see the effects of certain inefficiencies more. On a human level, so far I've been pleasantly surprised by the time it takes to render high-resolution images in release mode.

Currently there's no easy interface to create images, but if you want to play with the code in main.rs to change the image the program creates feel free to do so.

About

A simple CPU-based image raytracer build from scratch in Rust that utilizes a 3D Projective Geometric Algebra (PGA) centric approach to rendering.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages