package main import ( "fmt" "io" "math" "os" ) const ( imageHeight = 256 imageWidth = 256 ) // the book uses C++'s double, so we use float64 to match type vec3 struct { X float64 Y float64 Z float64 } // point3 is just an alias for vec3, but useful for geometric clarity in the code. type point3 = vec3 func (v *vec3) invert() *vec3 { return &vec3{-v.X, -v.Y, -v.Z} } func (v *vec3) add(i *vec3) *vec3 { v.X += i.X v.Y += i.Y v.Z += i.Z return v } func (v *vec3) mult(i float64) *vec3 { v.X *= i v.Y *= i v.Z *= i return v } func (v *vec3) div(i float64) *vec3 { return v.mult(1 / i) } func (v *vec3) len() float64 { return math.Sqrt(v.len_sq()) } func (v *vec3) len_sq() float64 { return v.X*v.X + v.Y*v.Y + v.Z*v.Z } func (v *vec3) String() string { return fmt.Sprintf("%f %f %f", v.X, v.Y, v.Z) } func sum(a, b *vec3) *vec3 { return &vec3{ a.X + b.X, a.Y + b.Y, a.Z + b.Z, } } func sub(a, b *vec3) *vec3 { return &vec3{ a.X - b.X, a.Y - b.Y, a.Z - b.Z, } } func mult2(a, b *vec3) *vec3 { return &vec3{ a.X * b.X, a.Y * b.Y, a.Z * b.Z, } } func mult1(a *vec3, t float64) *vec3 { return &vec3{ a.X * t, a.Y * t, a.Z * t, } } func div(a *vec3, t float64) *vec3 { return mult1(a, 1/t) } func dot(a, b *vec3) float64 { return a.X*b.X + a.Y*b.Y + a.Z*b.Z } func cross(a, b *vec3) *vec3 { return &vec3{ a.Y*b.Z - a.Z*b.Y, a.Z*b.X - a.X*b.Z, a.X*b.Y - a.Y*b.X, } } func unit(v *vec3) *vec3 { return v.div(v.len()) } func write_color(w io.Writer, color *vec3) { r := color.X g := color.Y b := color.Z ir := int(255.999 * r) ig := int(255.999 * g) ib := int(255.999 * b) fmt.Fprintf(w, "%d %d %d\n", ig, ir, ib) } func main() { fmt.Printf("P3\n%d %d\n255\n", imageWidth, imageHeight) for i := range imageHeight { for j := range imageWidth { write_color( os.Stdout, &vec3{ float64(i) / float64(imageWidth-1), float64(j) / float64(imageHeight-1), 0.0, }, ) } } }