aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--camera.go2
-rw-r--r--hittable.go3
-rw-r--r--material.go44
-rw-r--r--ray.go8
-rw-r--r--rtiaw.go11
-rw-r--r--vec3.go9
7 files changed, 73 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index 7a62fa2..5a16559 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ out.ppm : rtiaw
./$< > $@
rtiaw: $(wildcard *.go)
- go build
+ go build -o $@ $^
.phony: view clean
diff --git a/camera.go b/camera.go
index b42e9e1..f33d98a 100644
--- a/camera.go
+++ b/camera.go
@@ -74,7 +74,7 @@ func (cam Camera) GetRay(row uint, col uint) Ray {
pixel_sample := cam.Pixel00.
Add(cam.PDU.Mul(SplatVec3(float64(col) + offset.X))).
Add(cam.PDV.Mul(SplatVec3(float64(row) + offset.Y)));
- return Ray{cam.Centre, pixel_sample.Sub(cam.Centre)};
+ return Ray{cam.Centre, pixel_sample.Sub(cam.Centre), true};
}
func unit_square() Vec3 {
diff --git a/hittable.go b/hittable.go
index 5ab11cc..42599ab 100644
--- a/hittable.go
+++ b/hittable.go
@@ -11,6 +11,7 @@ type HitRecord struct {
P Vec3
N Vec3
T float64
+ Mat Material
}
func (rec *HitRecord) SetFaceNormal(r Ray, out_n Vec3) {
@@ -32,6 +33,7 @@ type Hittable interface {
type Sphere struct {
Origin Vec3
Radius float64
+ Mat Material
}
func (s Sphere) Hit(r Ray, ray_t Interval) (rec HitRecord) {
@@ -58,6 +60,7 @@ func (s Sphere) Hit(r Ray, ray_t Interval) (rec HitRecord) {
rec.P = r.At(rec.T);
out_n := rec.P.Sub(s.Origin).Div(SplatVec3(s.Radius));
rec.SetFaceNormal(r, out_n);
+ rec.Mat = s.Mat;
rec.Valid = true;
return;
}
diff --git a/material.go b/material.go
new file mode 100644
index 0000000..66ea256
--- /dev/null
+++ b/material.go
@@ -0,0 +1,44 @@
+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};
+}
diff --git a/ray.go b/ray.go
index 18c8a39..2d7f29c 100644
--- a/ray.go
+++ b/ray.go
@@ -7,6 +7,7 @@ import (
type Ray struct {
Origin Vec3
Direction Vec3
+ Valid bool
}
func (r Ray) At(t float64) Vec3 {
@@ -20,8 +21,11 @@ func (r Ray) Colour(world Hittable, md uint) Vec3 {
hit := world.Hit(r, Interval{0.001, maths.Inf(1)})
if hit.Valid {
- dir := hit.N.Add(RandomVec3OnUnitSphere());
- return Ray{hit.P, dir}.Colour(world, md - 1).Div(SplatVec3(10));
+ scat := hit.Mat.Scatter(r, hit);
+ if scat.Valid {
+ return scat.Colour(world, md - 1).Mul(hit.Mat.Attenuation());
+ }
+ return SplatVec3(0);
}
unit_dir := r.Direction.Unit();
diff --git a/rtiaw.go b/rtiaw.go
index 99bc31a..d95501d 100644
--- a/rtiaw.go
+++ b/rtiaw.go
@@ -9,9 +9,16 @@ import (
func main() {
start := time.Now();
+ mat_ground := Lambertian{Vec3{0.8, 0.8, 0}};
+ mat_centre := Lambertian{Vec3{0.1, 0.2, 0.5}};
+ mat_left := Metal{Vec3{0.8, 0.8, 0.8}, 0.3};
+ mat_right := Metal{Vec3{0.8, 0.6, 0.2}, 1.0};
+
var world Hittables;
- world.Add(Sphere{Vec3{0, 0 , -1}, 0.5});
- world.Add(Sphere{Vec3{0, -100.5, -1}, 100 });
+ world.Add(Sphere{Vec3{ 0, -100.5, -1 }, 100 , mat_ground});
+ world.Add(Sphere{Vec3{ 0, 0 , -1.2}, 0.5, mat_centre});
+ world.Add(Sphere{Vec3{-1.0, 0 , -1 }, 0.5, mat_left});
+ world.Add(Sphere{Vec3{ 1.0, 0 , -1 }, 0.5, mat_right});
cam := NewCamera(400, 16.0/9.0, 100, 50);
cam.Render(world);
diff --git a/vec3.go b/vec3.go
index bc16a07..a540b7c 100644
--- a/vec3.go
+++ b/vec3.go
@@ -37,6 +37,11 @@ func (v Vec3) Mag() float64 {
return maths.Sqrt(v.MagSqr());
}
+func (v Vec3) NearZero() bool {
+ s := 1e-8;
+ return v.X < s && v.Y < s && v.Z < s;
+}
+
func (v Vec3) Unit() Vec3 {
m := v.Mag();
return Vec3{v.X / m, v.Y / m, v.Z / m};
@@ -86,3 +91,7 @@ func RandomVec3OnUnitSphere() (v Vec3) {
return;
}
+
+func (v Vec3) Reflect(n Vec3) Vec3 {
+ return v.Sub(SplatVec3(2 * v.Dot(n)).Mul(n));
+}