class Camera def initialize(width = 100, aspect = 1.0, aliasing = 10) @width = width @aspect = aspect @aliasing = aliasing # Height @height = (@width / @aspect).to_i @height = @height < 1 ? 1 : @height # Camera c_focallength = 1.0 @c_centre = Point.new(0,0,0) # Viewport @v_height = 2.0 @v_width = @v_height * @width.to_f / @height v_u = Vec3.new(@v_width, 0, 0) v_v = Vec3.new(0, -@v_height, 0) # Pixel deltas @pd_u = v_u / @width @pd_v = v_v / @height # Upper left pixel v_upperleft = @c_centre - v_u / 2 - v_v / 2 - Vec3.new(0, 0, c_focallength) @p00_loc = v_upperleft + (@pd_u + @pd_v) / 2 end def render(world) start = Time.now.to_f puts "P3" puts "#{@width} #{@height}" puts "255" @height.times do |row| $stderr.print "Scanlines remaining: %4d" % (@height - row) @width.times do |col| p_colour = Colour.new @aliasing.times do p_colour += get_ray(row, col).colour(world) end puts (p_colour / @aliasing).to_ppm end puts end finish = Time.now.to_f took = finish - start $stderr.puts "Done. Took %4.2f seconds. " % took end def get_ray(row, col) p_sample = @p00_loc + @pd_u * (col + rand - 0.5) + @pd_v * (row + rand - 0.5) Ray.new(@c_centre, p_sample - @c_centre) end end