vkoskiv / c-ray

c-ray is a small, simple path tracer written in C
MIT License
797 stars 44 forks source link

Make the material system physically correct #75

Open madmann91 opened 4 years ago

madmann91 commented 4 years ago

Currently, the material system is not quite physically correct. Take for instance the diffuse material:

bool lambertianBSDF(struct hitRecord *isect, struct color *attenuation, struct lightRay *scattered, sampler *sampler) {                                                                     
      struct vector scatterDir = vecNormalize(vecAdd(isect->surfaceNormal, randomOnUnitSphere(sampler))); //Randomized scatter direction
      *scattered = ((struct lightRay){isect->hitPoint, scatterDir, rayTypeScattered});
      *attenuation = diffuseColor(isect);
      return true;
  }

The rendering equation is:

equation

The Lambertian BSDF is:

equation

Thus, if you want your MC estimator to be correct, you need to sample a direction equation according to some pdf equation and use it to evaluate the BSDF, then multiply that by the cosine and incoming light, and divide by that pdf. You then get the correct MC estimator:

equation

In the case of the Lambertian BSDF, that would give:

equation

Note that the incoming light equation is computed by pathTrace so that's already taken care of. In the current version of the code, the division by equation, the multiplication by the cosine, and the division by the sampling pdf are completely missing, though, and that's the case for every material in the framework. There are cases where you can avoid multiplying by the cosine, namely:

As far as I can see, the diffuse BSDF that you have doesn't fall into that category (it is not using cosine-weighted hemisphere sampling). Thus, I think it is not physically correct.

If you want references on the topic, I can recommend PBRT. It's not perfect, but it gets the points across. For a reference on the formulas, there's the very good GI compendium. If you want to discuss this further, I am on Discord and can get in touch if you're interested. Alternatively, if you think it's fine to leave this not physically correct, that's an option too, although I would not suggest to do that as solving visual bugs such as fireflies and the like will get harder.

vkoskiv commented 4 years ago

Currently, the material system is not quite physically correct.

You are absolutely right. In the past my priority has been what looks 'good enough', often with a rather lax definition of 'good enough'. It is about time we start putting an emphasis on physical correctness, so it's great that you pointed this out!

It's doubly-awkward that the material system is flawed when literally the first thing the README says is:

C-ray is a research oriented, physically accurate rendering engine built for learning.

Oops! 😅

The current set of materials, and in fact the entire material system has been inadequate for quite a while now. So a rework of these materials could be combined with an effort to improve the material system as a whole, perhaps with a simple node-based approach.

If you want references on the topic, I can recommend PBRT.

I actually own a physical copy! But as you can probably tell, I haven't put it to good use yet.

And yes, I would very much love to talk on Discord! You can find me at vkoskiv#3100 there.