Deluxe Render can do radiosity now!
Finite element radiosity is a rendering technique that is generally used to render perfectly diffuse scenes. Well, … that is about 20 years ago.
Radiosity saw its heyday in the 80’s and 90’s, and was even erroneously synonymous with “global illumination” for some time. But its limitations, including heavy memory usage, rigid model requirements, and diffuse surface materials, have relegated radiosity to limited usage in architecture and light map rendering. All these limitations have some exceptions in special versions of radiosity, but even the special versions can’t compete with modern techniques. Nowadays, ray tracing techniques like path tracing and photon mapping have replaced radiosity.
So why am I spending time working on a mostly outdated technique? I wrote the first draft of this code in the late nineties, and to me this is a chance to finish up something that took a lot of work, but wasn’t ever really finished. Also, it might let me try some things combining radiosity and ray tracing.
You might wonder why I’m using the word “we” below. I think of these posts as a conversation with whoever is reading. But in this case it’s the royal “we”. As in, “His majesty breaks the scene into some number of patches.”
In radiosity rendering, we break the scene into some number of patches. Here’s a room with a chair broken into patches, colored randomly so you can see them.
This scene was one I used earlier to write the first version of this radiosity renderer. It’s taken from Ian Ashdown’s book “Radiosity : A Programmer’s Perspective” (1994)
Each patch computes the visibility of all the other patches. Let’s consider a single patch we’ll color green, that accepts light from some other patches, we’ll color yellow. These colors aren’t really going to be used in the rendering. They’re just for clarity as we discuss the radiosity technique. Here, all patches visible to the green patch on the front side of the chair back are colored yellow. The green patch can only be lit by yellow patches. I might discuss how all this gets calculated in a future post.
The light coming from one of the yellow patches will make a contribution to the green patch depending on how big it is, how it’s oriented, and how far away it is. Without even thinking about brightness yet, we can compute this shape based term, also known as a form factor. If you want to see the math, read this Wikipedia article on form factors.
Form factors are stored as a percentage (they don’t have units) in a big array unless you’re using “progressive refinement” which computes form factors on the fly. For example, patch i might see 25% patch k, 25% patch l, and 50% patch m. Here’s a render with the form factors of the yellow patches relative to the green patch shown (brightened so we can see them).
Then, treating the whole scene as a linear system of equations, we can iterate light transport based on how bright patches are, and what their form factors are. In our example, patch i would collect light from patches k, l, and m scaled by their form factors. There are other methods of radiosity that push light instead of pulling it, but we’ll think about that later.
First, let’s look at the scene as an actual render, with 0 iterations of the patches collecting light from other patches through form factors.
So far, we have no illumination going on. The ceiling is white because the whole thing is actually a light source ready to pounce on the scene.
Let’s look at the scene after one iteration.
This is just direct illumination from the light on the ceiling. The ceiling is such a big source that the scene almost looks correct already, since it’s being handled correctly as an area light. The main clue we have that light hasn’t bounced is the black patch below the chair. Let’s switch to an example with a smaller light source.
Now, let’s look at two iterations. You’ll notice things get brighter overall. This is the light from the first illumination being pulled by all patches through their form factors in the second bounce.
What will this look like after 100 iterations if it gets brighter each time? Will it blow out to white?
You can see it’s only a little bit brighter. This is because each bounce gets a little dimmer as light is absorbed in the room (like in the real world), so we eventually reach an equilibrium (like in the real world).
Usually, these results are interpolated so that the result seems smoother:
Back in my day, those soft shadows were not easy to get without ray tracing. Go radiosity!
You might be thinking this looks a little dated. You’re right. Remember I said 80’s and 90’s before? It’s still a pretty neat technique, and there should be a scene that shows it off better in the future!
Before this post ends, though, here’s the same image as above, but with the saturation boosted so you can see the color spill. This is one effect that could be nice to show off with a better scene. Don’t worry about the color banding yet. The bleed from the apple is pretty clear.