# Controlling reflection and refraction with material properties in ray tracing

As tutors for this year’s programming languages course during our Computer Science studies we’re preparing for the students final project which is the implementation of a ray tracer. We’re implementing one on our own.

I’m having trouble understanding how the phong reflection model and reflection/refraction (Reflections and Refractions in Ray Tracing, Bram de Greve, 2006) can be used in conjunction.

Our materials currently have these properties:

• ka, kd, ks – ambient, diffuse and specular terms defined as RGB colors
• shininess – Controlling specular highlights (0 ≤ shininess)
• reflectivity – Controls degree of reflectivity (0 ≤ shininess ≤ 1, 0 means not reflective)
• refractive index – Defines the refractive index of the material (0 ≤ refractive index)

How I understand it, ray tracing as per phong reflection model with reflection and refraction works roughly like this:

1. The material is (semi)reflective and (semi)transparent (is this a word). In this case reflectivity and transmittance can be calculated with Fresnel equations. However then the reflectivity as specified in the material is ignored. The final color is reflectivity * trace(reflected_ray, depth + 1) + transmittance * trace(refracted_ray, depth + 1).
2. The material is (semi)reflective but not transparent. The reflective component is determined by further ray tracing. The other component is calculated via the equation from the Phong reflection model. Our ray tracer currently adds both components as in (1 - reflectivity) * color + reflectivity * trace(reflected_ray, depth + 1) where color is determined by the Phong equation.
3. The material is not reflective and not transparent. The Phong equation is used solely.

How do I know whether a material is (semi)transparent? Do I add a boolean property which I use to determine whether I’m in case 1 or 2?

• This isn't enough info to be a full answer obviously but the scattering function of the surface (aka BSDF) is what describes how light acts on a surface. The rendering equation includes the BSDF and shows how this stuff all fits together. I recommend checking out graphicscodex.com. It is 13 chapters long, where each chapter is only a few pages, but after you read through it (shouldn't take long) you'll have a deep understanding of this stuff. A deeper read would be anything on "physically based rendering" specifically the book at pbrt.com. Aug 22 '16 at 1:25
• Apologies, pbrt.org is the deeper read I mean. Aug 22 '16 at 1:37

It sounds to me like you're slightly mixing up several concepts: how lighting due to point-light sources (Phong model) and lighting due to other objects in the scene (recursively raytraced reflection or transmission) combine with each other, as compared to how specular lighting combines with diffuse lighting and/or transmission (using the Fresnel equations).

A useful way to think about specular vs diffuse is that specular happens at the surface of the material while diffuse, transmissive, and refractive properties are associated with the bulk (the interior) of the material. So you can think of it as two layers composited together. Specular is on top: it reflects a portion of the incoming light, defined by the Fresnel equations, and any remaining light proceeds into the material to light the bulk.

The bulk will have some combination of scattering and absorption properties. Low scattering makes a transmissive material and high scattering makes a diffuse material (the diffuse color is due to scattering on a scale too small to see). Some materials have an intermediate degree of scattering too, but we can ignore that for simplicity and just treat it as a boolean: opaque (Lambert diffuse) or transmissive.

Meanwhile, each of these potential material components (specular, diffuse, and transmissive) has to deal with light arriving both from point light sources and from the rest of the scene. Physically, all light sources are just emissive objects that are part of the scene (area lights) but again for simplicity we often approximate by using point lights.

So, putting it all together, when lighting a surface:

• For each point light
1. Calculate Fresnel factor based on light vector
2. Accumulate Phong specular weighted by Fresnel reflectance
3. [if opaque] Accumulate Lambert diffuse weighted by Fresnel transmittance
4. [if transparent] Nothing; light goes through and isn't scattered into the camera.
• For reflecting the rest of the scene
1. Calculate Fresnel factor based on view vector
2. Cast a reflection ray and accumulate it weighted by Fresnel reflectance
3. [if opaque] Nothing. (Ideally, accumulate Lambert diffuse due to all objects visible in the normal hemisphere of the surface, i.e. indirect diffuse. However, for a basic recursive raytracer this isn't feasible; it requires path tracing, photon mapping, or suchlike.)
4. [if transparent] Cast a transmission ray and accumulate it weighted by Fresnel transmittance

Also, a note about your material properties: physically, not all of those properties are actually independent of each other. Ks, reflectivity, and refractive index are all the same thing. Ks is the same thing as reflectivity (literally the same value) because both control specular reflections; Ks is for point lights and reflectivity is for reflected environment rays, but it's the same physical mechanism for both. And Ks is determined in turn by the Fresnel equations based on refractive index (which can vary with wavelength).

So, strictly speaking, you should pick one of those variables and let it determine the others. For opaque materials where you don't really care about refractive index, you might let users set Ks (at normal incidence) and backsolve the Fresnel equations to get the appropriate refractive index from that. For transparent materials like glass you can let users set the refractive index and then let the Fresnel equations do their thing.

BTW, to get some physics background that will hopefully help clarify all this, I highly recommend Naty Hoffman's "Physics and Math of Shading" talk from the SIGGRAPH 2015 Physically-Based Shading Course. It gives a quick and not-too-mathematical intro to the physical basis of things like diffuse and specular lighting, BRDFs and so on.

• I have questions. 1. In the "putting it all together" part you have a condition on whether an object is opaque or transparent. How do I determine this? Do I just add an opacity (or transparency) boolean value to my materials? 2. If ks is for point lights and reflectivity for reflected rays, how do I deduct one from the other as you suggest? There seems to be an equation taking refractive indices and calculating ks from that. (I'm still having a hard time really understand your complete answer. Bear with me, please. Thank you. :) Aug 26 '16 at 13:33
• @kleinfreund 1. Right, I'm suggesting a simplified material model where everything is either opaque (diffuse) or translucent, so you could use a boolean flag for this. 2. I'm saying ks and reflectivity are equal—literally the same value. Aug 27 '16 at 7:20
• I see. A isTransparent boolean attribute was added to our materials and I'm starting to replace the use of reflectivity with ks. The fresnel factor based on the light vector is calculated just as the one that is based on the view vector, correct? Instead of fresnel_reflectance(v, n, rI1, rI2) where rI are the refractive indices, I would do fresnel_reflectance(l, n, rI1, rI2) with the first parameter being the light vector instead of the view vector assuming the function is implemented correctly? (based on this paper, page 6) Aug 30 '16 at 15:25
• Ah! For opaque objects which I don't have a real refractive index for, I can determine that by using ks a.k.a. reflectivity as the solution for fresnel_reflectance(l, n, rI1, rI2) to get rI1. As for your section For reflecting the rest of the scene I would just use ks instead of calculating the Fresnel factor based on the view vector? Aug 30 '16 at 16:17
• Sorry for the confusion. I my last comment, instead of For reflecting the rest of the scene I meant For each point light and also the question concerns the light vector, not the view vector. Aug 30 '16 at 16:35