-
Notifications
You must be signed in to change notification settings - Fork 0
/
camera.t
201 lines (161 loc) · 5.59 KB
/
camera.t
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
include "set_pixel.t"
class camera
import vec3, ray, hit_record, iinit, fvmul, vadd, vinit, unit_vector, hittable, infinity, vsub, rinit, vSetPixel, winit, vfdiv, vvmul, random, interval
export aspect_ratio, image_width, render, inits, window_name, samples_per_pixel
% public
var aspect_ratio : real
var image_width : int
var samples_per_pixel : int
var window_name : string
% private
var image_height : int
var center : ^vec3
var pixel00_loc : ^vec3
var pixel_delta_u : ^vec3
var pixel_delta_v : ^vec3
var pixel_samples_scale : real
function ray_color(r : ^ray, world : ^hittable) : ^vec3
var rec : ^hit_record
var a : real
var col : ^vec3
new rec
var rc_a :^vec3 := vinit(1.0, 1.0, 1.0)
var rc_b :^vec3
var rc_i :^interval := iinit(0, infinity)
if (world -> hit( r, rc_i, rec )) then
rc_b := vadd(rec -> normal, rc_a)
col := fvmul(0.5, rc_b)
free rc_a
free rc_b
free rc_i
free rec
result col
end if
var rc_fa :^vec3
var rc_fb :^vec3
var unit_direction : ^vec3
unit_direction := unit_vector(r -> direction)
a := 0.5 * (unit_direction -> y + 1.0)
rc_b := vinit(0.5, 0.7, 1.0)
rc_fa := fvmul((1.0-a), rc_a)
rc_fb := fvmul(a, rc_b)
col := vadd(rc_fa, rc_fb)
free unit_direction
free rec
free rc_i
free rc_a
free rc_b
free rc_fa
free rc_fb
result col
end ray_color
procedure inits(ratio : real, width, samples : int, title : string)
image_width := width
aspect_ratio := ratio
samples_per_pixel := samples
window_name := title
end inits
% private
procedure initialize()
var focal_length : real
var viewport_height : real
var viewport_width : real
var viewport_u : ^vec3
var viewport_v : ^vec3
var viewport_upper_left : ^vec3
if (image_width div aspect_ratio) < 1 then
image_height := 1
else
image_height := (image_width div aspect_ratio)
end if
pixel_samples_scale := 1.0 / samples_per_pixel
winit(image_width, image_height, window_name)
center := vinit(0, 0, 0)
focal_length := 1.0
viewport_height := 2.0
viewport_width := viewport_height * (image_width / image_height)
viewport_u := vinit(viewport_width, 0, 0)
viewport_v := vinit(0, -viewport_height, 0)
pixel_delta_u := vfdiv(viewport_u, image_width)
pixel_delta_v := vfdiv(viewport_v, image_height)
viewport_upper_left :=
vsub(
vsub(
vsub(
center,
vinit(0, 0, focal_length)
),
vfdiv(viewport_u, 2)
),
vfdiv(viewport_v, 2)
)
pixel00_loc :=
vadd(
viewport_upper_left,
fvmul(
0.5,
vvmul(
pixel_delta_u,
pixel_delta_v
)
)
)
end initialize
function sample_square : ^vec3
result vinit(random(-0.5, 0.5), random(-0.5, 0.5), 0)
end sample_square
function get_ray(x, y : int) : ^ray
var pixel_sample : ^vec3
var ray_origin : ^vec3
var ray_direction : ^vec3
var offset : ^vec3
var gr_fa : ^vec3
var gr_fb : ^vec3
var gr_a : ^vec3
var res : ^ray
offset := sample_square
gr_fa := fvmul(x + offset -> x, pixel_delta_u)
gr_fb := fvmul(y + offset -> y, pixel_delta_v)
gr_a := vadd(gr_fa, gr_fb)
pixel_sample := vadd(pixel00_loc, gr_a)
ray_origin := center
ray_direction := vsub(pixel_sample, ray_origin)
res := rinit(ray_origin, ray_direction)
free offset
free gr_fa
free gr_fb
free gr_a
free pixel_sample
result res
end get_ray
procedure render(world : ^hittable)
initialize
var pixel_color : ^vec3
var r : ^ray
var rc : ^vec3
var final_color : ^vec3
new pixel_color
for x : 0 .. image_width
for y : 0 .. image_height
pixel_color -> initialize(0, 0, 0)
for sample : 0 .. samples_per_pixel
r := get_ray(x, y)
rc := ray_color(r, world)
pixel_color -> plus(rc)
free rc
free r
end for
final_color := fvmul(pixel_samples_scale, pixel_color)
vSetPixel(x, y, final_color)
free final_color
end for
end for
free pixel_color
end render
end camera
function cinit(ratio : real, width, samples_per_pixel : int, title : string) : ^camera
var c : ^camera
new c
c -> inits(ratio, width, samples_per_pixel, title)
result c
end cinit