The M_Dart Project is all about writing a book about Global Illumination and implementing a Ray Tracer in Ada 2012 to compute realistic pictures. The working title of the book is The M_Dart Project, with subtitle Computing Global Illumination by Ray Tracing using the Ada 2012 Programming Language
The reasons for starting this project are:
So I set myself out to try to develop a ray tracer that is rich in features, and write a book about it that covers both the theory as well as the practical implementation. One of the end goals is to encourage others to write a ray tracer or at least enjoy reading the book. It is my intention to combine theory and practical implementation, in order to help people new to the subject not to get scared by the sometimes complex theory and mathematics. A practical approach, tips & tricks, code snippets and the complete source code will be included to support any readers.
A first attempt to start this project was already in 2009, but due to my professional career and family life, it went dormant for quite a few years. Luckily, in 2014 I found myself again in a position to spend more time on it. I am still juggling time for my career, family and other hobbies. So I made some good progress until 2017, then it slowed down again for the same reason. I still make some progress every now and then, so keep checking back here.
On these pages, I want to keep you up to speed with the scope and progress of the project. I do not intent to distribute my book through here, although I might post some parts of it. In the end, if I ever get there, I intend to publish the book and see if I can get some money out of it, but that is not the prime objective. I intent to distribute the source code, likely in various stages of completion, and in order for you to understand what you might get, let me state the development environment I am using (and which is subject to change over time):
To keep readers informed about the scope and progress of my endeavors, I will start to maintain my product backlog and a simple blog-like diary on this page. Of course, intermediate results as pictures will be posted as well in the gallery.
Feel free to feedback any comments or questions you may have. Click here to email me. You can also leave a comment in the GitHub repository with the source code.
Finally, if you want to support me in my work, feel free to buy me a coffee via the button below. It is highly appreciated and helps me to continue my work.Picking up again after couple of years of silence...a few things have been added:
I implemented a simple reflective material, which basically allows you to add reflected light in the ideal direction. Also added a cosine term, so reflections in a more grazing angle to the reflective surface are more prominent, while reflections more perpendicular to the surface are less visible. Also built a more complex scene using CSG, which was worthwhile... the combination of reflection and more complex CSG objects led to two bugs I had to fix: A normal flipped in the wrong direction in my cube intersection code, and the CSG evaluation being cut off too early, resulting in some problems when subtracting an object from another CSG object. The result is rather pleasing though. It' also a good scene to test future acceleration algorithms.
I implemented a Phong material this period. At first it appeared to be straightforward, but with low, odd-powered parameters, it turned out I made a mistake in my code. Hence it took a bit longer to complete it, but finally it seems all to be working correctly. I do not enforce energy balance (i.e ambient + diffuse + specular reflection factor = 1.0), so I can actually be a bit more flexible with the materials, although physically not per se realistic. Below are some results...
Finally upgraded to newer hardware...see the revised spec above...Ran some tests and it is quite a bit faster, as expected. I have updated the times in the gallery accordingly. The first image went down from >5 mins to >1 mins, which is not bad at all. Also added some extra stats for CSG evaluation and length of the ShadePoint list. The CSG evaluation counts the number of times a CSG evaluation has been called on an object. As this is a recursive evaluation, even a simple CSG object like the ones in the previous posting will generate multiple CSG evaluations on average per ray intersection (ShadePoint). This is because my code evaluates upwards from any primitive object hit in the CSG tree.
Wow...this period was a challenge...I changed the planning a bit and started to implement Constructive Solid Geometry (CSG) a bit earlier. This turned out to be a bit more complex... Especially getting it to work with shadows was a bit of a struggle, but I finally got it working. See below for some example pictures.
This period I did some more work on the Filter code. I added skeleton code for Filter classes, and implemented a Box filter (all samples have an equal weight) and a Multi Stage Filter (the pixel is divided in a grid of 4x4 squares. The samples in each square are box-filtered, then the 16 square samples are box filtered). I also built a test scene containing a row of very thin cones, in alternating yellow and red colours. The cones are very thin and close to each other, such that their tops are much smaller than a pixel. They are also spread evenly but with a distance that is not matching the pixel distance. In other words, in pixel 1 the cone top may be in the centre, but in pixel 2 the top is slightly more to the right...and so forth... Therefore, rays will easily miss the tops of the cones, even with multiple rays per pixel. This scene is derived from Robert L. Cook's article "Stochastic Sampling in Computer Graphics". Below are a number of images where a random distribution of samples is compared with regular distribution.
Obviously, you can debate which picture is nicer to look at. Arguably, people may find the regular samples images prettier, but it is not about how pretty an image may be. It is all about how accurate it is. So in my mind, the saw-like patterns may be pleasing to see, but they are not accurately displaying the cones, which are all of the same height. Therefore, replacing aliases by noise will bring more realism in your images...if you bring the noise levels down to an acceptable level, by using more samples and appropriate filtering, you will get both realistic as pleasing images. I ran the images above also with higher sampling rates (up to 32x32 samples). Around 8x8 random samples, the noise becomes barely noticable, while the regular samples still show saw-like patterns and moire patterns.
This period I did some more work on the Sampling code. I added skeleton code to generate randomly distributed samples, but now with a minimal distance. This gives a more evenly distributed set of samples compared to pure random. I did not implement any specific filtering yet. All samples equally influence the pixel colour, which effectively means a box filter is used. A few examples of another checkered plane...note that the colours blend into yellow and light blue in the distance, although all squares are really just pure red, green or blue.
This weekend I worked on the Sampling Chapters. Part of this is showing how different sampling techniques impact quality of an image. To demonstrate this, see the images below of a checkered plane.
Feel free to feedback any comments or questions you may have. Click here to email me.