I'm trying to understand how a path tracer works and in the process I thought I should try to extend smallpt http://kevinbeason.com/smallpt/explicit.cpp to support triangles.

In the explicit light sampling part, there it sums all the unshadowed lights:

Code: Select all

`double omega = 2*M_PI*(1-cos_a_max);`

e = e + f.mult(s.e*l.dot(nl)*omega)*M_1_PI;

So the task is to compute "omega" for triangles. I implemented the method described at http://en.wikipedia.org/wiki/Solid_angle#Tetrahedron and it seems to work.

But there is one thing which bothers me. Solid angle is area divided by squared distance, right?

Code: Select all

`omega = A / r * r`

By cosine law, I should be able to "scale" the area by the dot product of light ray direction and the light triangle normal. (Btw., is this called "projected solid angle"?) In the above code, it would read:

Code: Select all

`scale = l.dot(normal_of_s)`

I tried it, and it seems to work, too.

So my questions is, or rather, my questions are:

- Why does it work? I mean, obviously, the two methods are different and the second one is much more simple - is the second method just an approximation which works only if, say, the solid angles are small enough?

- If it works, why to use the first method at all? I think I'm totally missing something, I would be thankful if someone could point me to the right direction.

Thanks in advance!