Reyes Renderer

Ideas, enhancements, feature requests and development related discussion.

Re: Reyes Renderer

Postby dcuny » Thu Jan 08, 2009 10:36 pm

The sad truth is that I'm not a particularly clever coder, and algorithms that require a strong handle on math are hard for me. I can eventually get them working, but debugging tends to be a real pain. For example, it took a lot of time before I could get the Approximate Ambient Occlusion (AAO) code working, and I never really got Irradiance Caching working properly. (Hrm... I just found a trove of papers on Irradiance Caching). And the AAO code, which should have been really fast, turned out not to be that fast at all. (The fault there probably lies with having to restructure to 3D data, not the basic algorithm).

Now, raytracing is relatively easy, which is why I was able to have some level of success with Inyo, The hard part there is getting it to render things fast enough. For example, AO is simply a matter of shooting off a bunch of random rays, and recording how many hit something nearby. (Even there, I had trouble!)

Acceleration techniques often involve something clever, which means you have to have a solid understanding of it when you start debugging things. Otherwise, you won't be able to identify what's going wrong.

They also tend to eat up a lot of memory, because they rely on caching stuff. For simple scenes, that's not a problem. But it's amazing how quickly memory gets eaten up once you drop an infinite plane into a scene, or have half a dozen objects in. For example, Inyo handles first-hit rendering pretty well. But once you add reflective or transparent objects to the scene, all bets are off. So often, what initially appears promising

But I ramble...

I did some more reading on DSMs, and think I finally have a good handle on them. That's good if ever decide I really want to use the for hair or some such. Unfortunately, they turn out not to be useful for what I had intended. They'll give you a value that represents the occlusion for a point in space from a light's point of view. But the estimate only tells how much occlusion there is at a given point - not how distant the occlusion is.

The clever part of DSMs is that it takes a bunch of samples, and creates a piecemeal approximation. I'm not sure that you can linearly approximate the distance of the next object in the depth.

Really, what I need to do is stop writing about this and start working on code again. But that's probably not going to happen for a couple of weeks - I've just been too busy with other things (and sick).
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Sat Jan 24, 2009 12:07 pm

I'm hopeful that I'm starting to get over whatever cold/flu/whatever I've got. I'm still falling asleep way too early in the evening, but I'm starting to feel better, and starting to get excited about the prospect of coding again.

I've pretty much decided that the Marin shaders are not going to be RenderMan compliant. It's just way too much work, and I'm not up for that challenge. I may still have programmable shaders, but they're likely to be less clever in their approach to lights.

I had written a little renderer to test out the subdivision code before importing it into Marin. It's able to load .obj files and render them, but it's a bit stupid. Instead of implementing a zbuffer, I just sorted all the triangles by z depth. This was good enough to test out the subdivision code, but it would be really nice to have a zbuffer renderer to test out the screen-based ambient occlusion instead of using Marin.

I found some Java code that works pretty well. It uses edge equations to determine if a point is in the triangle, so it's essentially got the same core as Marin. Thanks to accompanying online lectures, I think I've got a reasonable grasp on some of the finer points of the renderer. (Recall I'm a bit dense when it comes to math).

So the current plan is to bolt the triangle rasterizer onto my little renderer, and see if I can generate zbuffer information usable to play with ambient occlusion. If that works, I'm sure it'll take me a while to get the AO code to actually work. So I should be busy for a while. If the results are encouraging, I'll either try adding that to Marin, or developing the zbuffer renderer a bit further. I'd talked about that idea before. For example, the stuff I'd done with the OpenGL renderer (environment maps and spherical harmonics) as well as ideas pilfered from Reyes (subpixel sampling, hierarchical zbuffer) that I'd like to explore.
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Sat Jan 31, 2009 10:23 am

I've made some progress hacking the new rendering code together with my old .obj loader and subdivision code. There are some bugs in it, though - I've got pixels dropping out in various places. I also haven't implemented the interpolation code yet, so it's just flat shading and using the smallest z depth across the triangle. I've got the interpolation code sitting here, I just haven't had time to type it in.

I'm itching to get this working, but I've promised to work on other projects first. I really want to start playing with SSAO... :?
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby sascha » Tue Feb 10, 2009 3:23 pm

That's the first time I've seen the words "emacs" and "feeble" associated together. It's usually "emacs" and "everything and the kitchen sink."

Site Admin
Posts: 2792
Joined: Thu May 20, 2004 9:16 am
Location: Austria

Re: Reyes Renderer

Postby pndragon » Tue Feb 10, 2009 6:48 pm

"We're so sorry, Uncle Albert,
But we haven't done a bloody thing all day."
--- Paul McCartney
Posts: 591
Joined: Sun Dec 05, 2004 1:27 am
Location: North Carolina

Re: Reyes Renderer

Postby John VanSickle » Wed Feb 11, 2009 2:06 pm

Every programmer has XKCD in his bookmarks, if not as his home page.
John VanSickle
Posts: 189
Joined: Sat Feb 16, 2008 2:17 am

Re: Reyes Renderer

Postby dcuny » Thu May 20, 2010 6:22 pm

The pain of working on this project must be starting to fade, because I'm getting the urge to start working on it again. I'm not really sure that there's a good reason for doing so. I've revisited Sascha's subdivision code, and it seems to me that he can effectively get micro-polygon resolution from the SDS tesselator that he's developed.

Two strengths of the Reyes algorithm are motion blur and focal blur.

Motion blur in Reyes requires that you supply a motion path for the primitives, and by default is linear. This makes it fairly cheap to implement, but it doesn't really work in 3D. With a fast enough z buffer renderer, you can simply render multiple frames and average them together.

Focal blur is also "free" in Reyes, but can also be simulated with a z buffer fairly cheaply, with good results.

So the reasons for writing a Reyes renderer become less and less compelling. But that's never stopped me before. ;)

One thing I'd like to try to do differently is handling the micropolygons. There's a "bust" phase in Reyes where the grid is converted into micropolygons, and each micropolygon is then tested to see what samples in screen space it covers.

In some cases, a micropolygon may overlap the screen bucket that the grid is placed in. In that case, it has to be re-inserted into the rendering queue as a primitive.

My approach was to place the micropolygon back into the rendering queue in the next bucket.

The problem here is that there can be a lot of micropolygons in the queue. And before rendering, the queue is sorted by z depth for more efficient depth culling. That's pretty expensive.

I think a better approach would be to never create a "micropolygon" in the first place. The grid has already holds all the information needed to describe the micropolygon's geometry and color. These values can be passed on to the "hider" portion of Reyes without needing to create a micropolygon. Instead of inserting the micropolygons into the rendering queue, the grid itself could be inserted. Flags can be set in the grid over which micropolygons can be safely ignored. After rendering a grid, the bounds of the remaining micropolygons could be recalculated, so the "hider" could more accurately do depth culling on the entire grid.

So that's my main motivation - my implementation of Reyes was really, really slow. I think dropping micropolygons as objects could speed things up a lot.
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Mon May 24, 2010 6:34 pm

Still more reading on Reyes. One of the suggestions from Production Rendering book I've been going through is that it's a good idea to create a hybrid renderer, with the raytracer handing things light effects:

  • Accurate simulation of reflection and refraction
  • Global illumination algorithms
  • Photon mapping
All of these are great, but since I don't have a render farm, I don't know if I can afford any of these effects. :?

A commenter on this thread notes:
For these reasons PRman is probably the most terrible raytracing capable renderer ever made (I have to deal with it every day for at least 10 hours a day)... but almost none of the other render engine on the market can handle displacement and motionblur well enough to deliver a film quality imagery. Those two are some of the most important features needed to make a CG image look real and integrated with a live-action plate... This is probably the reason why PRman is still the product of choice of many VFX/animation houses.

Still, I've already got a raytracer, so it's tempting to try bolting it onto Marin and see what happens. One of the biggest questions is determining the level of tesselation. There seem to be two approaches here. The first uses multi-resolution tesselation based on ray differentials. This approach is used in PRMan, among others.

The second approach is simpler: geometry is projected onto a unit circle. That is, a ray is created starting from the eyepoint, and running through the geometry point. The ray is then normalized, and the end point used as the projected point. The advantage here is that you can use the Reyes tesselator to generate the geometry, which is pretty cool. I'm thinking that's the direction I should take.

The downside with either approach is that you're not likely to be able to hold all the geometry in memory, so you've got to create a geometry cache. Probably not that difficult, but I haven't written one before so I've been avoiding it.

Since Reyes allows motion blur (with motion paths), the raytracer would need to be extended to handle that as well. It's not a huge change, but it would make things a bit slower - and raytracing is already slow.

If I go this route, I'll probably code up a toy raytracer using the Reyes tesselator and no acceleration structures. If that works, I can go ahead and turn it into something usable. If not, I'll stick with a pure scanline renderer.

One of the real timesinks while working on Marin was the shading language support. I think a better approach would probably have been to use something like BeanShell instead of writing the compiler from scratch. It would still need to support a SIMD sort of approach, but I wouldn't have to spend time writing a VM to run the script, which ate up a lot of time.

All this is still exploratory, since I'm probably a couple months away from having enough free time to start working on the renderer again.
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Tue May 25, 2010 6:46 pm

While browsing around for graphics stuff, I ran across this website with lots of cool Java applets, including raytraced ambient occlusion and depth of field with bokek effects. Neat stuff, even if I'd already implemented that kind of thing before. ;)

Anyway, playing around with the ray traced AO convinced me again that it's really, really slow and ray tracing is probably not where I should be focusing my time. I've been stuck trying to get SSAO (Screen Space Ambient Occlusion) working, but all the methods are pretty low-quality and have artifacts when animated. (I still plan on looking at raytracing, but it's now much lower on my priority list).

So it looks like point-based approximate ambient occlusion (AAO) is the way to go. I've already implemented approximate AO some time back. I'd abandoned it for a couple of reasons:

  • The implementation required tessellating objects to a high degree, which my code didn't support.
  • Blender had an awesome implementation of AAO.
So I stopped working on the project and started working on a tool to import models to Blender. Unfortunately, I couldn't figure out how to call Blender's AAO from batch mode, so that project died. :(

It's been a while since I've played with my AAO code, and my recollection was that it ran pretty slowly. Re-reading my posts, I see that was true - before I implemented a k-d tree lookup. D'oh! From my notes, it looks like the AAO is actually quite fast. The slow bit is figuring out shared vertices and such - something that I don't have to do under Reyes. :roll:

So I've already got a fairly nice tool for calculating AAO. (Assuming I still have a good backup somewhere).

The other reason for abandoning it was that I needed to have large polys (like the group plane) tessellated finely. Passing a dataset like that to OpenGL would take a huge amount of time.

Of course, tessellating geometry down to micropolygons is exactly what Reyes does. Sometimes I feel like a complete moron. :oops:

It's been a long time since I've looked at Marin. My initial plan was to rewrite the "hider" and get rid of micropolygons as primitives. (Marin is not a very fast renderer).

If the basic code is working, I'll see if I can bolt in the AO code without changing too much. It would probably make more sense to write a new AAO hider that generates the point cloud. I can probably strip out the "classic" hider that I've got without too much trouble (assuming that it's not terribly broken).
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Wed May 26, 2010 6:45 am

I've gotten a hold of one of the older versions of Marin and added a new Hider class based around a simple zbuffer.
Rendered with Marin's new zbuffer hider
zbuffer.png (30.67 KiB) Viewed 5248 times

Of course, it doesn't do any of the good stuff, like buckets, antialiasing, motion blur, focal blur, and so on. Here's a similar image using the "classic" Reyes buffer, which took about 10 times longer:
Rendered with the "classic" Reyes buffer
classic.png (32.33 KiB) Viewed 5248 times

Hrm... Looks like I don't have the anti-aliasing enabled there.

It can render the image at 1000x1000 in about 38 seconds. The "classic" version takes much, much longer - around 10 minutes. That's good news for me, because it means Marin is potentially usable. (Note the grey "background" is actually a quad which is being diced down to size).

Now I need to go through my old code and see if I can find an .obj file loader, and the approximate ambient occlusion code. :P
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Wed May 26, 2010 11:13 pm

I've been working with an older version of the Marin codebase, which is probably a bad idea, since I'll have to port the code forward once it's working.

I also had to revisit a number of bugs that had gotten corrected later. For example, the "sample inside the micropoly" test assumed that the micropoly vertices were in clockwise order. The solution is simple - add the reverse test - but I wasted time getting it to work.

The older code also doesn't support bicubic splines, so I'm converting everything to polygons, which ultimately get converted into quads.

Anyway, here's another image rendered using the zbuffer:
Mesh object rendered using a zbuffer hider.
zbuffer_1.png (35.56 KiB) Viewed 5245 times

The model has one level of subdivision added to it, using the subdivision code I wrote a while back. It's fast enough for testing purposes, but I can't add another level of subdivision without running out of memory.

I'm not going to bother tracking down the cracks in the triangle, since that's probably a one-off bug that got fixed in Marin.

So the next thing to work on is adding AAO. There's a three day weekend coming up, and I may take a couple vacation days to work on the code. :)
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Thu May 27, 2010 8:42 am

After a number of false starts, I've got it generating point clouds. Well, actually occlusion disk clouds, since each "point" is actually the location of an occlusion disk, which tracks it's location, size and normal:
Point cloud created by renderer.
point_cloud.png (5.13 KiB) Viewed 5240 times

This version of the code isn't clever enough to make a micropolygon larger than a pixel, because the shading rate is directly related to the size of the micropolygon grid. I should rewrite that code at some point, but I don't want to get too distracted from the goal.

The next step is to plug the occlusion code into the shading system... :?
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Thu May 27, 2010 1:00 pm

I've got AAO working to some degree. Here's an image without AAO:
Rendered without AAO.
without_aao.png (35.45 KiB) Viewed 5239 times

And the same model with AAO:
Rendered with AAO.
with_aao.png (45.36 KiB) Viewed 5239 times

Note the effect isn't very strong, especially near the hairline. That's because I've got an ad hoc chunk of code that discards contributions that are deemed "too strong". It's not a very good solution, but I'll explore better solutions later.

I think another issue is that the models don't have normals, so there's over contribution from samples.

There are other problems, such as "pinching" artifacts:
Example of "pinching" artifacts.
aao_pinching.png (44.4 KiB) Viewed 5239 times

The solution to this problem is discussed in GPU Gems.

There's also a relationship between the shading rate of the sample points and the occlusion weight calculations. As the GPU Gems article discusses, you've got to be careful with some of the values, or you lose fine details. So I guess I'll be reviewing the articles again in detail tomorrow. :(
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Thu May 27, 2010 1:30 pm

I've gone back and changed the equations back to what was in the original GPU Gems article, and the results are pretty good:
Better AAO.

Most of the fine detail is there, and it lacks the sort of artifacts I'd been seeing. Changing various attributes doesn't seem to make it go wonky like it had been doing, which is a good thing. But I've still got an ad hoc maximum value I'll accept from each occlusion disk to prevent it from going bad. I'd like to try to get rid of that.

The ponytail looks odd because the normals are reversed on it. I'll need to get the .obj file loader working to see how it handles larger scenes.

It takes two or three seconds to generate the points, and about 55 seconds to render the image. That's faster than raytraced AO, but not very competitive with anything else. More elements in the scene means it takes longer to render. But it's too early to start thinking about speeding the code up.

I've rendered the same scene with spheres, and the AO seems to work fine across multiple objects. So the main thing at this point is to try to get some models that have the normals correct, to verify that it works with other models as well.
Posts: 2902
Joined: Fri May 21, 2004 6:07 am

Re: Reyes Renderer

Postby dcuny » Fri May 28, 2010 8:26 am

I got the .obj file importer working. Here's the Suzanne model (exported from Blender):
Plain rendering of "Suzanne" exported from Blender using the z buffer.
suzanne_plain.png (43.21 KiB) Viewed 5236 times

Here's the point cloud:
Point cloud of "Suzanne" model.
suzanne_point_cloud.png (21.62 KiB) Viewed 5236 times

And here's the model rendered with only AAO:
"Suzanne" model rendered with AAO.
suzanne_with_aao.png (49.48 KiB) Viewed 5236 times

The largest factor so far for speeding up rendering with AAO is the determination at what point to use a proxy instead of continuing to search the Kd Tree for more disks:
Code: Select all
      // further than tolerance? (16 is default)
      if (d2 > Reyes.PROXY_DISTANCE * proxy.area) {
         // use proxy
Changing the PROXY_DISTANCE from 16 to 4 speeds up the rendering from 55 seconds to 20 seconds, with no noticeable difference in quality.

Here's a shot of a render with "pinching" artifacts.
"Pinching" artifacts.
pinching.png (19.85 KiB) Viewed 5236 times

I still haven't implemented a generic solution for this. The the ad hoc filter value does a pretty good job, but it also removes a lot of the sharp shadows. :(

I think I'll take a break from the AAO code to play with some other features for a while. Spherical harmonics should be easy to implement, since I've got the code handy from another project. I'm on the fence about whether I should try out shadow maps, or add raytracing. It's been a long time since i've worked with Inyo. So long, in fact, the I'd forgotten what I called the project, and I can't find any code lying around on my machine. I pulled down a copy from Inyo, so I guess I should have a look through that... :?
Posts: 2902
Joined: Fri May 21, 2004 6:07 am


Return to Development

Who is online

Users browsing this forum: No registered users and 2 guests