From 218a0340bce4a298e74fd81aaa05309a92d7bdd3 Mon Sep 17 00:00:00 2001 From: Luxdragon Date: Tue, 27 Feb 2024 20:04:26 +0100 Subject: [PATCH] Camera struct --- main.go | 138 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 57 deletions(-) diff --git a/main.go b/main.go index 1d476a0..8f82e69 100644 --- a/main.go +++ b/main.go @@ -277,75 +277,99 @@ func (hl Hittable) Hit(r *Ray, ray_t Interval, rec *Hit_record) bool { return hit_anything } -func Ray_color(r Ray, world *Hittable) Vec3 { +// =============== CAMERA =================== + +type Camera struct { + aspect_ratio float32 + image_width int + image_height int + center Vec3 + pixel00_loc Vec3 + pixel_delta_u Vec3 + pixel_delta_v Vec3 +} + +func NewCamera() *Camera { + return &Camera{} +} + +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) } unit_direction := Unit_vector(r.Direction()) a := (unit_direction.Y() + 1.0)*0.5 - return NewColor(1.0,1.0,1.0).Mult(float32(1.0-a)).Add(NewColor(0.5,0.7,1.0).Mult(a)) - } +func (cam *Camera) Initialize() { + // Calculate the image height + cam.image_height = int(float32(cam.image_width) / cam.aspect_ratio) + if cam.image_height < 1 { + cam.image_height = 1 + } + // Viewport + var focal_length float32 = 1.0 + var viewport_height float32 = 2.0 + var viewport_width float32 = viewport_height * float32(cam.image_width)/float32(cam.image_height) + cam.center = NewVec3(0,0,0) + + // Calculate the vectors across the horizontal and down the vertical viewport edges + viewport_u := NewVec3(viewport_width, 0, 0) + viewport_v := NewVec3(0, -viewport_height, 0) + + //Calculate the horizontal and vertical delta vectors from pixel to pixel + cam.pixel_delta_u = viewport_u.Div(float32(cam.image_width)) + cam.pixel_delta_v = viewport_v.Div(float32(cam.image_height)) + + // Calculate the location of the upper left pixel + viewport_upper_left := cam.center.Sub(cam.center).Sub(NewVec3(0, 0, focal_length)).Sub(viewport_u.Div(2)).Sub(viewport_v.Div(2)) + cam.pixel00_loc = viewport_upper_left.Add((cam.pixel_delta_u.Add(cam.pixel_delta_v)).Div(2)) +} + +func (cam *Camera) Render(world *Hittable) { + cam.Initialize() + + // Rendering + fmt.Println("P3") + fmt.Println(cam.image_width, " ", cam.image_height, "\n255") + 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) + } + } +} + + + // =============== MAIN ===================== func main() { + // World - // Image - aspect_ratio := 16.0 / 9.0; - var image_width int = 400; + world := NewHittable() + world.Add(Sphere{ + center: NewVec3(0, 0, -1), + radius: 0.5, + }) + world.Add(Sphere{ + center: NewVec3(0, -100.5, -1), + radius: 100, + }) + // Image - // Calculate the image height - var image_height int = int(float64(image_width) / aspect_ratio) - if image_height < 1 { - image_height = 1 - } - - // World - - world := NewHittable() - world.Add(Sphere{ - center: NewVec3(0, 0, -1), - radius: 0.5, - }) - world.Add(Sphere{ - center: NewVec3(0, -100.5, -1), - radius: 100, - }) + cam := NewCamera() + cam.aspect_ratio = 16.0 / 9.0 + cam.image_width = 400 - // Camera - var focal_length float32 = 1.0 - var viewport_height float32 = 2.0 - var viewport_width float32 = viewport_height * float32(image_width)/float32(image_height) - camera_center := NewVec3(0,0,0) - - // Calculate the vectors across the horizontal and down the vertical viewport edges - viewport_u := NewVec3(viewport_width, 0, 0) - viewport_v := NewVec3(0, -viewport_height, 0) - - //Calculate the horizontal and vertical delta vectors from pixel to pixel - pixel_delta_u := viewport_u.Div(float32(image_width)) - pixel_delta_v := viewport_v.Div(float32(image_height)) - - // Calculate the location of the upper left pixel - viewport_upper_left := camera_center.Sub(camera_center).Sub(NewVec3(0, 0, focal_length)).Sub(viewport_u.Div(2)).Sub(viewport_v.Div(2)) - pixel00_loc := viewport_upper_left.Add((pixel_delta_u.Add(pixel_delta_v)).Div(2)) - // Rendering - fmt.Println("P3") - fmt.Println(image_width, " ", image_height, "\n255") - for j := 0; j < image_height; j++ { - fmt.Fprintf(os.Stderr, "\rScanlines remaining: %d ", image_height-j) - for i := 0; i < image_width; i++ { - pixel_center := pixel00_loc.Add(pixel_delta_u.Mult(float32(i))).Add(pixel_delta_v.Mult(float32(j))) - ray_direction := pixel_center.Sub(camera_center) - r := NewRay(camera_center, ray_direction) - - pixel_color := Ray_color(*r, world) - Write_color(pixel_color) - } - } - // INFO: The pixels are written out in rows. - // Image file can be created with - // go run main.go > image.ppm + cam.Render(world) + // INFO: The pixels are written out in rows. + // Image file can be created with + // go run main.go > image.ppm } \ No newline at end of file