2
votes

I am doing a project about ray tracing, right now I can do some basic rendering.

The image below have:

mirror reflection, refraction, texture mapping and shadow.

enter image description here

I am trying to do the glossy reflection, so far this is what I am getting. Could anyone tell me if there is any problem in this glossy reflection image?

enter image description here

In comparison, the image below is from the mirror reflection

enter image description here

This is my code about glossy reflection, basically, once a primary ray intersect with an object. From this intersection, it will randomly shot another 80 rays, and take the average of this 80 rays color. The problem I am having with this code is the magnitude of x and y, I have to divide them by some value, in this case 16, such that the glossy reflect ray wouldn't be too random. Is there anything wrong with this logic?

             Colour c(0, 0, 0);

                     for (int i = 0; i < 80; i++) {

                          Ray3D testRay;
                          double a = rand() / (double) RAND_MAX;
                          double b = rand() / (double) RAND_MAX;
                          double theta = acos(pow((1 - a), ray.intersection.mat->reflectivity));
                          double phi = 2 * M_PI * b;
                          double x = sin(phi) * cos(theta)/16;
                          double y = sin(phi) * sin(theta)/16;
                          double z = cos(phi);
                          Vector3D u = reflect.dir.cross(ray.intersection.normal);
                          Vector3D v = reflect.dir.cross(u);
                          testRay.dir = x  * u + y * v  + reflect.dir;
                          testRay.dir.normalize();

                          testRay.origin = reflect.origin;
                          testRay.nbounces = reflect.nbounces;
                          c = c + (ray.intersection.mat->reflectivity)*shadeRay(testRay);
                     }
                     col = col + c / 80;
1
a and b will have a random value between 0 and 1 - fiftyplus
FWIW, I don't think your code is entirely correct - the glossy reflection of the green ellipsoid should be symmetrical about the view axis. - Alnitak

1 Answers

5
votes

Apart from the hard coded constants which are never great when coding, there is a more subtle issue, although your images overall look good.

Monte-Carlo integration consists in summing the integrand divided by the probability density function (pdf) that generated these samples. There are thus two problems in your code:

  • you haven't divided by the pdf although you seem to have used a pdf for Phong models (if I recognized it well ; at least it is not a uniform pdf)
  • you have further scaled your x and y components by 1./16. for apparently no reason which further changes your pdf.

The idea is that if you are able to sample your rays exactly according to Phong's model times the cosine law then you don't even have to multiply your integrand by the BRDF. In practice, there are no exact formula that allow to sample exactly a BRDF (apart from Lambertian ones), so you need to compute:
pixel value = sum BRDF*cosine*incoming_light / pdf
which mostly cancels out if BRDF*cosine = pdf.

Of course, your images overall look good, so if you're not interested in physical plausibility, that may as well be good.
A good source about the various pdfs used in computer graphics and Monte-Carlo integration (with the appropriate formulas) is the Global Illumination Compendium by Philip Dutré.