1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
class Camera
def initialize(width = 100, aspect = 1.0,
aliasing: 10, depth: 10, vfov: 90.0,
lookfrom: Point.new(0, 0, 0),
lookat: Point.new(0, 0, -1),
vup: Vec3.new(0, 1, 0),
defocus_angle: 0, focus_dist: 10)
@width = width
@aliasing = aliasing
@depth = depth
# Height
@height = (@width / aspect).to_i
@height = @height < 1 ? 1 : @height
# Camera
@c_centre = lookfrom
# Viewport
theta = vfov * Maths::PI / 180
h = Maths.tan(theta / 2)
v_height = 2.0 * h * focus_dist
v_width = (v_height * @width) / @height
# Camera basis vectors
w = (lookfrom - lookat).unit
u = vup.cross(w).unit
v = w.cross(u)
v_u = u * v_width
v_v = -v * v_height
# 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 -
w * focus_dist
@p00_loc = v_upperleft + (@pd_u + @pd_v) / 2
@defocus_angle = defocus_angle
defocus_radius = focus_dist * Maths.tan((@defocus_angle / 2) *
Maths::PI / 180)
@defocus_disk_u = u * defocus_radius
@defocus_disk_v = v * defocus_radius
end
def render(world)
start = Time.now.to_f
puts "P3"
puts "#{@width} #{@height}"
puts "255"
@height.times do |row|
$stderr.print "[GScanlines remaining: %4d" % (@height - row)
@width.times do |col|
p_colour = Colour.new
@aliasing.times do
p_colour += get_ray(row, col).colour(world, @depth)
end
puts (p_colour / @aliasing).to_ppm
end
puts
end
finish = Time.now.to_f
took = finish - start
$stderr.puts "[GDone. 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_origin = @defocus_angle <= 0 ? @c_centre : defocus_disk_sample
ray_dir = p_sample - ray_origin
Ray.new(ray_origin, ray_dir)
end
def defocus_disk_sample
p = Vec3.random_in_unit(dimensions: 2)
@c_centre + @defocus_disk_u * p.x + @defocus_disk_v * p.y
end
end
|