Photorealistic Path Tracer
thume.ca
thume.ca
Edit: And at least right before I go to bed my post technically made it on the front page in the very last slot :)
I'm also glad people like my ray tracer, it was super satisfying to build, and nice to have a project that I know I put substantial effort into and can really be proud of.
The person that comes up with a sorting algorithm is not on some different scale than the person that makes a game or controls a machine. BTW, I'm not quite sure how to interpret the bird in your sentence.
And nope, I wouldn’t know where to start to do anything in 3D graphics. But I can throw together a microservice API
I used that exact card to do real time rendering of simulated toolpaths for a 3D mill. That was mind-blowing at the time, to have an array of voxels large enough that you could do something meaningful with it and to be able to display the results as it was running.
Many people I have listened to started with basic and programming at an early age.
Oh yeah and your webpage has plenty of other great pieces too. Thanks for this!
I haven't read the meta programming thing yet but I really enjoyed reading the thing about the path tracer.
P.S. I wish Trains (CS452) had something so demo-able. ;)
So when I heard that he was giving a town hall talk at the end of his stint I definitely wanted to check it out.
What I walked into was a 30 minute take down of Liquid, the template language that I wrote. He systemically took every single design decision I made and dismembered it based on language design fundamentals.
That was still one of my favorite townhalls. As a self taught programmer it also send me to read about compiler and language theory for the next years to better understand all the errors of my ways. Thanks Tristan!
We have since rewritten liquid mostly in C and it has a strict parser mode that’s done with proper approach instead of my hacky regexp based approach.
One example is `{% if this && that %}`, which is not the correct syntax for logical and but people write in Liquid templates and see that it doesn't give an error so expect it to work, but actually it acts the same as `{% if this %}` and just ignores the invalid suffix.
I remember hearing you mention my talk when I was back at Shopify a couple years later (context for others: my first internship I was in grade 11 but I went back 2 times, Shopify is great) and realizing that at many other companies giving a talk in front of everyone about design flaws in the CEO's code would be a career limiting move. But I think it's a testament to Shopify's culture that this never occurred to me in grade 11 and in fact it was instead appreciated.
When the Mandelbox came up I was fully expecting some sort of explanation about how they thought it was so cool the author had to 3D print it.
At this point I was like “I wonder if they are going to model their desk from earlier?” I was actually delighted and ecstatic when I figured out my mistake! Wonderful work, truly.
It manages to tackle both the math and the gritty details of implementing the math. Blew me away the first time I read it.
I read it cover to cover before doing much, but then made sure I wrote things how I wanted without referencing the book except for a few bits of formula-heavy code I mention in the credits.
Definitely the best technical book I've ever read.
I used to read programming books cover to cover 25 years ago when I was in High School/College. I don't do it so much these days, the books aren't as useful and I know too much so most of it ends up being redundant now.
If you're learning something new you can consume voraciously.
I would also recommend that method, if you have time for it.
The literate programming style used works very well, making it easy to follow the code as the authors works it out and how it connects with the math or more abstract ideas.
Of course, it's not light reading so reading it in bed might indeed be sleep inducing. But that's hardly something you can hold against it.
The author links to past year galleries: https://www.student.cs.uwaterloo.ca/~cs488/gallery-A5.html
I'm not sure if this was done in all the years, but one of the interesting (and slightly unfair) aspects of the final project was that you were not only graded on the quality of the final render, but also how closely you aligned to your plan as stated up front. That is, if you planned an ambitious render BUT had to scale down to something slightly less ambitious (due to difficulty or time-constraints), your mark would be lower than the individual who planned a simple render and executed that.
In my experience, the students who take the project courses at UW are ambitious and driven. I suspect the chief effect of this policy is an ambitious project whose plan has been fleshed out by a healthy back-and-forth with the TAs upfront, vs a ridiculously ambitious project that hasn't been fleshed out.
There's also marks for artistry and humour, and getting perfect in the other categories doesn't require as much work as I put in. I didn't get a perfect mark and I suspect it's because I blew past the cap for technical difficulty but lost some marks on artistry and originality.
And, as an item of nostalgia, here is some of my glossy mirror code:
if(matl->t == M_GLOSSMIRROR){
double θ0 = acos(cosθ), Δθ = M_PI * matl->rough / 2, lθ, dθ = 2*Δθ/ray->w, dφ = 2*dθ, θ, φ;
lθ = (θ0 - Δθ) < 0 ? 0 : ((θ0 + Δθ) < M_PI ? (θ0 - Δθ) : (M_PI - 2*Δθ));
θ = lθ + (p+RAND1)*dθ; φ = -2*Δθ + (q+RAND1)*dφ;
v4 z = hit->n, x = norv4(subv4(ray->p, scv4(dotv4(ray->p, z), z))), y = crv4(x, z);
...I assume you did this in RGB space, so no pretty prisms? I couldn't find any explicit mention. From the report I guess you didn't implement refraction at all?
Spectral leads to great images, but the color space conversions are such a pain to get correct.
It’s a lot easier to learn from than the pbrt one in my opinion.
There are ways to avoid having to do single wavelength rays (hero wavelengths or basis functions) but it’s tricky.
Ray tracing is fun! Writing code that simulates physical optics and generates a photorealistic image can be very gratifying. Many years ago, I dabbled in ray tracing briefly and it was exciting. I have archived some of the code here, in case, you want to take a look:
- https://github.com/mycask/java-ray-tracing (A very rudimentary orthographic ray tracer written from scratch in Java)
- https://github.com/mycask/pov-ray-tracing (Examples written while learning POV-Ray)
The reflection of the cube in the stapler is too sharp, like a perfect mirror finish.
The book in the background seems to lack and sort of ambient occlusion.
Still a good scene, it's the fact these stand out so much to me is evidence of how good it is :)
Disclaimer: I'm in the middle of my first keyboard build, modified from an existing 3d-printable design. The left half works already. I'll probably blog about it when it's finished.
As for languages, I guess that depends on how long you are willing to wait for results. You might be able to use Go or something on the JVM without driving yourself insane.
Ray casting (1968) was simply casting rays from camera, one per each image pixel, until the ray hits the closest object. Then the pixel gets the color from the object.
Ray tracing (1979) made ray casting recursive for three cases:
1. Reflection: The object surface is a perfect mirror, so we calculate the reflection angle from the incoming ray angle, and continue the process.
2. Refraction: The object is transparent, like glass. The Fresnel equations give the refraction (transmission) and reflection angles and the distribution of energy between them. For some angles, one of these can be 0.
3. Shadow ray: Shadow rays are traced towards each light source. If the shadow ray is blocked by any other object, we're in shadow in respect of that light source. If a light source is visible, both the light source color and the object surface color contribute to the color of this pixel. The object surface can also have a reflectance model (BRDF) so it doesn't need to be a matte Lambertian surface, but the BRDF is only applied to light coming directly from the light sources.
An object can have partially reflective surface (like glossy plastic), and it can also be partially transparent (like colored glass). So at each intersection, we may generate up to all 3 types of rays.
What we miss here, is that all surfaces diffusely reflect light to some amount, and that the colors in all diffuse incoming light from every direction contributes to the color of a surface, not just direct light from visible light sources. (We also miss caustics. Most notably, a transparent glass ball between the surface and a light source will only give a shadow in ray tracing.)
Historically, there was a time when computers were too slow for sampling, even statistically weighted importance sampling, of diffuse light coming from all directions to all surfaces. So the above model of handling only 3 types of rays (mirror reflection, transparent object refraction, light directly from a light source) became both popular, and established as ray tracing.
Then later, advances towards including all kinds of physically possible light rays, adopted names other than ray tracing. They are still tracing rays, but they are not called tray tracing, because the name ray tracing is understood to mean only the first method that got widely popular, with all its limitations.
Then, when doing the regular ray/path tracing, at each intersection of the camera-ray, you see if the intersection location is near any of the light-ray hits. If so, add in some contribution from the light-ray hits.
This avoids you having to explicitly check each light at each intersection point, saving you quite a number of visibility tests. Also, due to the smoothing kernel used when the "photon contributions" are added up, it leads to low-frequency noise rather than high-frequency noise that is normal in regular path tracing. This is especially noticeable when caustics are involved.
A nice introduction to the technique can be found here: https://web.cs.wpi.edu/~emmanuel/courses/cs563/write_ups/zac...