package main //Material type Material interface { Attenuation() Vec3 Scatter(r Ray, hit HitRecord) Ray } //Lambertian type Lambertian struct { Albedo Vec3 } func (l Lambertian) Attenuation() Vec3 { return l.Albedo; } func (l Lambertian) Scatter(r Ray, hit HitRecord) Ray { scat_dir := hit.N.Add(RandomVec3OnUnitSphere()); if scat_dir.NearZero() { scat_dir = hit.N; } return Ray{hit.P, scat_dir, true}; } //Metal type Metal struct { Albedo Vec3 Fuzz float64 } func (m Metal) Attenuation() Vec3 { return m.Albedo; } func (m Metal) Scatter(r Ray, hit HitRecord) Ray { refl := r.Direction.Reflect(hit.N).Unit(). Add(SplatVec3(m.Fuzz).Mul(RandomVec3OnUnitSphere())); valid := refl.Dot(hit.N) > 0; return Ray{hit.P, refl, valid}; }