(Task 6) Materials - cmu462/Scotty3D GitHub Wiki

Now that you have implemented the ability to sample more complex light paths, it's finally time to add support for more types of materials (other than the fully Lambertian material provided to you in the starter code). In this task you will add support for two types of materials: a perfect mirror and glass (a material featuring both specular reflection and transmittance).

To get started take a look at the BSDF interface in bsdf.cpp. There are a number of key methods you should understand:

  • BSDF::f(wo,wi) evaluates the distribution function for a given pair of directions.
  • BSDF::sample_f(const Vector3D& wo, Vector3D* wi, float* pdf) generates a random sample wo (which may be a reflection direction or a refracted transmitted light direction). The method returns the value of the distribution function for the pair of directions, and the pdf for the selected sample wi.

There are also two helper functions in the BSDF class that you will need to implement:

  • BSDF::reflect(w0, ...) returns a direction wi that is the perfect specular reflection direction corresponding to wi (reflection of w0 about the normal, which in the surface coordinate space is [0,0,1]). More detail about specular reflection is here.

  • BSDF::refract(w0, ...) returns the ray that results from refracting the ray w0 about the surface according to Snell's Law. The surface's index of refraction is given by the argument ior. Your implementation should assume that if the ray w0 is entering the surface (that is, if cos(w0,N) > 0) then the ray is currently in vacuum (index of refraction = 1.0). If cos(w0,N) < 0 then your code should assume the ray is leaving the surface and entering vacuum. In the case of total internal reflection, the method should return false.

Step 1

Implement the class MirrorBSDF which represents a material with perfect specular reflection (a perfect mirror). You should Implement MirrorBSDF::f(), MirrorBSFD::sample_f(), and BSDF::reflect(). (Hint: what should the pdf sampled by MirrorBSFD::sample_f() be? What should the reflectance function f() be?)

Step 2

Implement the class GlassBSDF which is a glass-like material that both reflects light and transmit light. As discussed in class the fraction of light that is reflected and transmitted through glass is given by the dielectric Fresnel equations, which are documented in detail here. Specifically your implementation should:

  • Implement BSDF::refract() to add support for refracted ray paths.
  • Implement GlassBSDF::sample_f(). Your implementation should use the Fresnel equations to compute the fraction of reflected light and the fraction of transmitted light. The returned ray sample should be either a reflection ray or a refracted ray, with the probability of which type of ray to use for the current path proportional to the Fresnel reflectance. (e.g., If the Fresnel reflectance is 0.9, then you should generate a reflection ray 90% of the time. What should the pdf be in this case?) Note that you can also use Schlick's approximation instead.
  • You should read the provided notes on the Fresnel equations as well as on how to compute a transmittance BSDF.

When you are done, you will be able to render images like these: width=600px