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
|
#!/usr/bin/env ruby
start = Time.now.to_f
$LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
require 'interval'
require 'vec3'
require 'ray'
require 'hittable'
def ray_colour(ray, world)
if rec = world.hit(ray, Interval.new(0, Float::INFINITY))
return (Colour.new(1,1,1) + rec.normal) * 0.5
end
unit_dir = ray.direction.unit
a = (unit_dir.y + 1) / 2
Colour.new(1.0, 1.0, 1.0) * (1-a) + Colour.new(0.5, 0.7, 1.0) * a
end
# Define image
width = 400
aspect = 16.0 / 9
max = 255
# Calculate height
height = (width / aspect).to_i
height = height < 1 ? 1 : height
# World
world = Hittables.new
world << Sphere.new(0,0,-1, 0.5)
world << Sphere.new(0,-100.5,-1, 100)
# 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 -
Vec3.new(0, 0, c_focallength) -
v_u / 2 -
v_v / 2
p_00loc = v_upperleft +
(pd_u + pd_v) / 2
puts <<-EOH
P3
#{width} #{height}
#{max}
EOH
height.times do |row|
$stderr.print "[GScanlines remaining: %4d" % (height - row)
width.times do |col|
p_centre = p_00loc + (pd_u * col) + (pd_v * row)
ray_dir = p_centre - c_centre
ray = Ray.new(c_centre, ray_dir)
p_colour = ray_colour(ray, world)
puts p_colour.to_ppm
end
puts
end
finish = Time.now.to_f
took = finish - start
$stderr.puts "[GDone. Took %4.2f seconds. " % took
|