Chapter 8 - Metal
In Chapter 7, the text introduced diffuse materials by hard-coding behavior into Ray and main. Chapter 8 is called 'Metal', but starts by focusing on the concept of a material. It suggests two critical aspects of a material:
- How it scatters rays
- How it attenuates the rays when they are scattered
As I write this, it's a bit confusing to think about absorbing some rays and attenuating rays. The text gives me the option to handle this as I see fit, but the code provided suggests
The first task is to reimplement our diffuse (Lambertian) material from Chapter 7 using this abstraction. The original C++ implements this as a class, material, with a method scatter, and re-uses hit_record to pass a bunch of parameters to the scatter method, and returns a boolean, destructively modifying a provided Ray to pass back the scattered ray. In Lua, I decided to pass back a Ray regardless:
-- Lambertian material
Lambertian = {}
function Lambertian:new(o)
o = o or {}
self.__index = self
setmetatable(o, self)
return o
end
-- Parameters:
-- ray: [Ray] The incoming ray to scatter
-- hit_record: [HitRecord] The HitRecord associated with its impact
-- attenuation: [Vector3] How much the ray's color should be attenuated
function Lambertian:scatter(ray, hit_record, attenuation)
target = hit_record:p() + hit_record:normal() + random_in_unit_sphere()
return Ray:new{hit_record:p(), target - hit_record:p(), ray:world()}
end