Blog Archive About

Psychopath Renderer

a slightly psychotic path tracer

2014 - 08 - 01

Drawbacks of Geometry Caches

At the end of my post about ray reordering I alluded to some problems I ran into with using geometry caches and ray reordering. In this post I'm going to talk about the problem I ran into with geometry caching.

Geometry caching in-and-of itself isn't particularly problematic. But it can become a problem if you're trying to share it between multiple threads. The issue is that with an LRU cache even just reading from the cache is a write operation, because you have to move the read item to the front of the cache. And that means locking. And locking means thread contention.

I think I was actually reasonably smart in the way I wrote the cache. The cache treats the cached data as read-only, so it only needs to be locked long enough to move the accessed item to the front and then fetch a shared pointer to the data. That is a very short period of time, certainly far less than the tracing done with the geometry afterwards.

The result of that cleverness was that rendering with eight cores sped up rendering by about 5-6x. That's nothing to sneeze at considering that the cache was being accessed for every ray-object intersection test. But it was a clear indication that it wouldn't scale well with too many more cores. And on eight cores, you really want close to an 8x speed up if you can get it.

2014 - 07 - 28

Ray Reordering

In my last rendering architecture post I talked about using geometry caching to ray trace micropolygons. But Psychopath didn't stay there.

It wasn't long after making the first micropolygon renders that I stumbled across the paper Two-Level Ray Tracing with Reordering for Highly Complex Scenes by Hanika et al. Instead of using a geometry cache to ray trace diced surfaces, Hanika et al. used something called "ray reordering".

With standard ray tracing you trace one ray at a time, doing all of its intersection tests against all relevant parts of the scene before moving on to the next ray. But with ray reordering you instead queue up many rays at once and attempt (as best you can) to explicitly change the order of the ray tests, with the goal of testing many rays against the same part of the scene at once.

There are many different ways to go about this, but typically it involves some mechanism that lets you pause a ray's traversal through the scene. If you have such a mechanism, you can then pause a ray just before it's tested against an object in the scene. Once the ray is paused, you can move on to other rays in the hopes that some of them will also be paused before that same object. When you have enough rays paused before an object, you can unpause all of them together and do the ray tests for that object all at once.

2014 - 07 - 07

Glossy Fixed! And the GTR Microfacet BRDF

So, I've fixed the obvious bug in the glossy BRDF from my last post.

GTR Glossy

The bug was in the fresnel calculation. I was doing a dot product with one of the vectors unormalized, when it was supposed to be normalized. This caused the dot product to be greater than one in some areas, which made the result of the whole equation negative when taken together. Fun!

The glossy BRDF still isn't 100% there yet. I'm still struggling to figure out what I'm doing wrong with one part of the equation (for now I'm just leaving that part out, and it still looks believable—when I include it, things explode with brightness, so I must be doing something wrong). But that will be for another post.

But still! Looks cool!

Now that I have it more-or-less working, I want to talk briefly about what makes this particular glossy BRDF cool.

As I mentioned before, this BRDF uses the GTR (or Generalized Trowbridge-Reitz) microfacet distribution. Like most glossy BRDF's, it has a parameter for how blurry the reflections are. But unlike most glossy BRDF's, it also has a parameter for the shape of the blurriness. And when I say "shape" I don't mean like stars or squares or circles. Rather, I mean this:

2014 - 07 - 06

Glossy Render

Everything still uses a single shader, but I've now implemented a much better glossy BRDF.

GTR Glossy

It's based on the "Generalized Trowbridge-Reitz" or GTR microfacet distribution presented in Disney's Principled BRDF paper. GTR is pretty much identical to GGX, except that it has an additional parameter to tweak the tail of the specular highlight.

There are still some bugs in the implementation (see, for example, the black spot on the lip of the teacup). And I'm still struggling to figure out certain things about microfacet BRDF's in general. But it's more-or-less working, with proper importance sampling and everything.

I'm especially pleased to see it working in the context of the curved surfaces, since they're rendered using micro-geometry. I'm not seeing any artifacts originating from that.

2014 - 07 - 06

First Phong Render

So, this has been a long time coming. Psychopath's first non-lambert-shaded render.

First Phong

The bsdf itself is totally throw-away code (the importance sampling isn't good at all, hence the noise). But it's done via the bsdf system I've put in place. And it works! So, yay!

There's still lots more work to do to get a proper shader system working. You may notice that all of the surfaces still use the same hard-coded bsdf, for example.

But nevertheless! I'm excited.

Although it does feel kind of silly to be so excited about this, given that phong is such a basic thing. For most renderers this is like "Hello World". But for Psychopath, with its weird-ass ray tracing kernel, it's taken a while to get here.