Chapter 8 done

This commit is contained in:
Luxdragon 2024-02-28 15:20:31 +01:00
parent 268f1a0156
commit 75adfbcdb5
2 changed files with 3209 additions and 3158 deletions

6294
image.ppm

File diff suppressed because it is too large Load diff

73
main.go
View file

@ -3,7 +3,14 @@ package main
import "fmt" // for IO and standard library
import "os" // for handling the progress bar
import "math" // for maths
import "unsafe"
import "unsafe" // for fast inverse square pointers
import "math/rand" // for random
import "time" // for random
func init() {
rand.Seed(time.Now().UnixNano())
}
// ================ VEC3 CLASS =====================
@ -117,10 +124,28 @@ func Degrees_to_radians(degrees float32) float32 {
return (degrees * pi) / 180.0
}
func RandomDouble() float32 {
// Returns a random real in [0,1).
return rand.Float32()
}
func RandomDoubleInRange(min, max float32) float32 {
// Returns a random real in [min,max).
return min + (max-min)*RandomDouble()
}
// ============== COLOUR CLASS ==============
func Write_color(v Vec3) {
fmt.Println(int(255.999*v.E[0]), int(255.999*v.E[1]), int(255.999*v.E[2]))
func Write_color(v Vec3, samples_per_pixel int) {
// Averaging
r := v.X() / float32(samples_per_pixel)
g := v.Y() / float32(samples_per_pixel)
b := v.Z() / float32(samples_per_pixel)
// Write the translate [0, 255] value of each color component
intensity := NewInterval(0.000, 0.999)
fmt.Println(int(intensity.Clamp(r)* 256.0), int(intensity.Clamp(g)* 256.0), int(intensity.Clamp(b)* 256.0))
}
func NewColor(e0, e1, e2 float32) Vec3 {
@ -187,6 +212,15 @@ func (i *Interval) Surrounds(x float32) bool {
return i.min < x && x < i.max
}
func (i *Interval) Clamp(x float32) float32 {
if (x < i.min) {
return i.min
} else if (x > i.max) {
return i.max
}
return x
}
var Empty *Interval = NewInterval()
var Universe *Interval = NewInterval(float32(math.Inf(-1)), float32(math.Inf(1)))
@ -287,13 +321,14 @@ type Camera struct {
pixel00_loc Vec3
pixel_delta_u Vec3
pixel_delta_v Vec3
samples_per_pixel int
}
func NewCamera() *Camera {
return &Camera{}
}
func Ray_color(r Ray, world *Hittable) Vec3 {
func Ray_color(r Ray, world *Hittable) Vec3 {
var rec Hit_record
if (world.Hit(&r, *NewInterval(0, float32(math.Inf(1))), &rec)) {
return rec.normal.Add(NewColor(1,1,1)).Mult(0.5)
@ -337,16 +372,32 @@ func (cam *Camera) Render(world *Hittable) {
for j := 0; j < cam.image_height; j++ {
fmt.Fprintf(os.Stderr, "\rScanlines remaining: %d ", cam.image_height-j)
for i := 0; i < cam.image_width; i++ {
pixel_center := cam.pixel00_loc.Add(cam.pixel_delta_u.Mult(float32(i))).Add(cam.pixel_delta_v.Mult(float32(j)))
ray_direction := pixel_center.Sub(cam.center)
r := NewRay(cam.center, ray_direction)
pixel_color := Ray_color(*r, world)
Write_color(pixel_color)
pixel_color := NewColor(0,0,0)
for sample := 0; sample < cam.samples_per_pixel; sample++ {
r := cam.GetRay(i, j)
pixel_color = pixel_color.Add(Ray_color(*r, world))
}
Write_color(pixel_color, cam.samples_per_pixel)
}
}
}
func (cam *Camera) GetRay(i, j int) *Ray {
// Get a randomly sampled camera ray for the pixel at location i,j
pixel_center := cam.pixel00_loc.Add(cam.pixel_delta_u.Mult(float32(i))).Add(cam.pixel_delta_v.Mult(float32(j)))
pixel_sample := pixel_center.Add(cam.Pixel_sample_square())
ray_direction := pixel_sample.Sub(cam.center)
return NewRay(cam.center, ray_direction)
}
func (cam *Camera) Pixel_sample_square() Vec3 {
// Returns a random point in the square surrounding a pixel at the origin
px := -0.5 + RandomDouble()
py := -0.5 + RandomDouble()
return (cam.pixel_delta_u.Mult(px).Add(cam.pixel_delta_v.Mult(py)))
}
// =============== MAIN =====================
@ -367,7 +418,7 @@ func main() {
cam := NewCamera()
cam.aspect_ratio = 16.0 / 9.0
cam.image_width = 400
cam.samples_per_pixel = 100
cam.Render(world)
// INFO: The pixels are written out in rows.
// Image file can be created with