# Can someone explain radiosity lighting to me?

I already have the basics of ambient occlusion down. I have a raycaster and am capable of shooting rays about a hemisphere uniformly. It seems like those are the basics of what are needed for radiosity but I don't know where to go from there. Do I find how much light comes from each face? (I'm making my game out of cubes like minecraft) After that what do I do?

-
Why the tag "minecraft"? – Valmond Aug 27 '11 at 7:57

Indeed, that is all you need for radiosity. There are two different (but equal) formulations. The first is to "radiate" or shoot light from each patch (in your case probably a face), and the other is to "gather" or receive light into each patch. If you iteratively do this enough times, you get radiosity.

The first step is to figure out where light originates from because in either method there must be a light source. If you are going to do the gather method, I must warn you that it does not handle point lights very well. You must seed patches with light (calculate it separately) or you get odd results. In the radiate method you emit from the point lights as normal but ignore them as receivers from other patches.

You can stop after any number of bounces (or iterations), but the more you do, the better the solution. You have an easy time of patch creation as you can consider each side of your cubes as a patch. If you want something more detailed you can subdivide those faces even farther.

In a radiating example, this could be used as a basis for your loop:

``````while(!done) {
foreach Patch a {
a.shootRays(n);
foreach ray r {
Patch b = r.firstIntersectingPatch();
float modifier = 1 / ((distance(a,b)^2)
b.incidentLight += (a.exidentLight / n) * modifier;
}
}
foreach Patch a {
float modifier = a.absorption;
a.exidentLight = (a.incidentLight * modifier) + a.emission;
a.incidentLight = 0;
}

done = goodEnough() ? true : false;
}
``````

For a gather method, you would have the slightly different first loop:

``````      foreach Patch a {
a.shootRays(n);
foreach ray r {
Patch b = r.firstIntersectingPatch();
float modifier = 1 / ((distance(a,b)^2)
a.incidentLight += b.exidentLight * modifier;
}
a.incidentLight /= n;
}
``````

The first modifier is used for per patch modification of the incoming light. The most common use would be falloff from distance as I did above. The second modifier is for global modification of incoming light like material absorption. The a.emission variable would be 0 for most patches.

Only those that are light sources (or directly affected by point light sources if you are using a gather method as noted above) should have non 0 emission values.

The goodEnough() function could be many things. It could be just counting the number of iterations, or it could be looking at the total amount of light in the scene, or it could be some other test you devise. This part is really up to you and what you think looks good enough but still finishes in a reasonable amount of time.

The more rays you shoot, the more accurate your solution but the slower the process. The same goes for number of patches and number of iterations through the loop. How you store the final light value is up to you. It could be in a texture, or stored as a value in your cubes, but I don't think this would be feasible to do in real-time with a decent number of patches.

-
Hello Chewy. Does this really work? I'm pretty sure that it should consider lambert's cosine law. But maybe i don't get something. – Notabene Aug 27 '11 at 23:16
It can get as physically accurate as you want. The angles between the patches can be taken into account with the first modifier value, along with any number of other phenomena. This is just the general outline of what happens. – Chewy Gumball Aug 27 '11 at 23:31
Ok. Very nice. This is the first time i hear about radiosity in ray casting fashion. But it makes perfect sense. Thank you for it. – Notabene Aug 28 '11 at 0:12

On the link bellow you will find one of the most excellent explanations of radiosity:

It is worth reading even if you know it well. So funny :)

-