aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--color.go6
-rw-r--r--hitable.go18
-rw-r--r--main.go7
-rw-r--r--material.go16
4 files changed, 33 insertions, 14 deletions
diff --git a/color.go b/color.go
index 857bc41..bb7318a 100644
--- a/color.go
+++ b/color.go
@@ -32,10 +32,8 @@ func RayColor(ray Ray, hitable_list HitableList, depth int) Color {
}
hit := hitable_list.Hit(ray, T_MIN, T_MAX)
if hit.time > 0.0 {
- // TODO: Use the correct distribution
- direction := AddVec3D(hit.normal, RandomInUnitSphere())
- scattered := Ray{hit.point, direction}
- return AttenuateColor(Color{0.5, 0.5, 0.5}, RayColor(scattered, hitable_list, depth+1))
+ scattered, attenuation := hit.material.Scatter(ray, hit)
+ return AttenuateColor(attenuation, RayColor(scattered, hitable_list, depth+1))
}
param := 0.5 * (ray.direction.Unit().y + 1)
return LinearBlend(Color{0.5, 0.7, 1.0}, Color{1.0, 1.0, 1.0}, param)
diff --git a/hitable.go b/hitable.go
index bc9f9bc..ef5822f 100644
--- a/hitable.go
+++ b/hitable.go
@@ -3,9 +3,10 @@ package main
import "math"
type HitRecord struct {
- time float64
- point Vec3D
- normal Vec3D
+ time float64
+ point Vec3D
+ normal Vec3D
+ material Material
}
type Hitable interface {
@@ -16,7 +17,7 @@ type Hitable interface {
type HitableList []Hitable
func (hitable_list HitableList) Hit(ray Ray, t_min float64, t_max float64) HitRecord {
- closest_hit := HitRecord{T_MAX, Vec3D{}, Vec3D{}}
+ closest_hit := HitRecord{T_MAX, Vec3D{}, Vec3D{}, nil}
for _, hitable := range hitable_list {
hit := hitable.Hit(ray, t_min, closest_hit.time)
if hit.time > 0 {
@@ -31,8 +32,9 @@ func (hitable_list HitableList) Hit(ray Ray, t_min float64, t_max float64) HitRe
}
type Sphere struct {
- center Vec3D
- radius float64
+ center Vec3D
+ radius float64
+ material Material
}
func (sphere Sphere) Normal(point Vec3D, ray Ray) Vec3D {
@@ -55,12 +57,12 @@ func (sphere Sphere) Hit(ray Ray, t_min float64, t_max float64) HitRecord {
time := (-b - root) / (2.0 * a)
if t_min < time && time < t_max {
point := ray.PointAt(time)
- return HitRecord{time, point, sphere.Normal(point, ray)}
+ return HitRecord{time, point, sphere.Normal(point, ray), sphere.material}
}
time = (-b + root) / (2.0 * a)
if t_min < time && time < t_max {
point := ray.PointAt(time)
- return HitRecord{time, point, sphere.Normal(point, ray)}
+ return HitRecord{time, point, sphere.Normal(point, ray), sphere.material}
}
}
return HitRecord{}
diff --git a/main.go b/main.go
index 291e60f..b8f6335 100644
--- a/main.go
+++ b/main.go
@@ -20,8 +20,11 @@ func main() {
VERTICAL := Vec3D{0.0, 2.0, 0.0}
CAMERA := Camera{LOWER_LEFT_CORNER, ORIGIN, HORIZONTAL, VERTICAL}
- SPHERE := Sphere{Vec3D{0.0, 0.0, -1.0}, 0.5}
- EARTH := Sphere{Vec3D{0.0, -100.5, -1.0}, 100.0}
+ MAT_RED := Lambertian{Color{0.7, 0.3, 0.3}}
+ MAT_GREEN := Lambertian{Color{0.8, 0.8, 0.0}}
+
+ SPHERE := Sphere{Vec3D{0.0, 0.0, -1.0}, 0.5, MAT_RED}
+ EARTH := Sphere{Vec3D{0.0, -100.5, -1.0}, 100.0, MAT_GREEN}
WORLD := HitableList{EARTH, SPHERE}
frame := Frame{}
diff --git a/material.go b/material.go
new file mode 100644
index 0000000..db1e4d6
--- /dev/null
+++ b/material.go
@@ -0,0 +1,16 @@
+package main
+
+type Material interface {
+ Scatter(ray Ray, hit HitRecord) (Ray, Color)
+}
+
+type Lambertian struct {
+ albedo Color
+}
+
+func (lambertian Lambertian) Scatter(ray Ray, hit HitRecord) (Ray, Color) {
+ // TODO: Use the correct distribution
+ direction := AddVec3D(hit.normal, RandomInUnitSphere())
+ scattered := Ray{hit.point, direction}
+ return scattered, lambertian.albedo
+}