@@ -12,10 +12,13 @@ const N: u32 = 64;
12
12
const MAX_STEP : u32 = 64 ;
13
13
const MAX_DISTANCE : f64 = 2.0 ;
14
14
const EPSILON : f64 = 1e-6 ;
15
+ const BIAS : f64 = 1e-4 ;
16
+ const MAX_DEPTH : u32 = 3 ;
15
17
16
18
struct Res {
17
19
sd : f64 ,
18
20
emissive : f64 ,
21
+ reflectivity : f64 ,
19
22
}
20
23
21
24
impl std:: ops:: Add < Res > for Res {
@@ -62,14 +65,17 @@ fn scene(x: f64, y: f64) -> Res {
62
65
let a = Res {
63
66
sd : circle_sdf ( x, y, 0.4 , 0.2 , 0.1 ) ,
64
67
emissive : 2.0 ,
68
+ reflectivity : 0.0 ,
65
69
} ;
66
70
let b = Res {
67
71
sd : box_sdf ( x, y, 0.5 , 0.8 , 2.0 * PI / 16.0 , 0.1 , 0.1 ) ,
68
72
emissive : 0.0 ,
73
+ reflectivity : 0.9 ,
69
74
} ;
70
75
let c = Res {
71
76
sd : box_sdf ( x, y, 0.8 , 0.5 , 2.0 * PI / 16.0 , 0.1 , 0.1 ) ,
72
77
emissive : 0.0 ,
78
+ reflectivity : 0.9 ,
73
79
} ;
74
80
a + b + c
75
81
}
@@ -133,13 +139,21 @@ fn gradient(x: f64, y: f64) -> (f64, f64) {
133
139
( nx, ny)
134
140
}
135
141
136
- fn trace ( ox : f64 , oy : f64 , dx : f64 , dy : f64 ) -> f64 {
142
+ fn trace ( ox : f64 , oy : f64 , dx : f64 , dy : f64 , depth : u32 ) -> f64 {
137
143
let mut t = 0.0 ;
138
144
let mut i = 0 ;
139
145
while i < MAX_STEP && t < MAX_DISTANCE {
140
- let r = scene ( ox + dx * t, oy + dy * t) ;
146
+ let x = ox + dx * t;
147
+ let y = oy + dy * t;
148
+ let r = scene ( x, y) ;
141
149
if r. sd < EPSILON {
142
- return r. emissive ;
150
+ let mut sum = r. emissive ;
151
+ if depth < MAX_DEPTH && r. reflectivity > 0.0 {
152
+ let ( nx, ny) = gradient ( x, y) ;
153
+ let ( rx, ry) = reflect ( dx, dy, nx, ny) ;
154
+ sum += r. reflectivity * trace ( x + nx * BIAS , y + ny * BIAS , rx, ry, depth + 1 ) ;
155
+ }
156
+ return sum;
143
157
}
144
158
i += 1 ;
145
159
t += r. sd ;
@@ -151,7 +165,7 @@ fn sample(rng: &mut ThreadRng, x: f64, y: f64) -> f64 {
151
165
let mut sum = 0.0 ;
152
166
for i in 0 ..N {
153
167
let a = 2.0 * PI * ( i as f64 + rng. gen_range ( 0.0 , 1.0 ) ) / N as f64 ;
154
- sum += trace ( x, y, a. cos ( ) , a. sin ( ) ) ;
168
+ sum += trace ( x, y, a. cos ( ) , a. sin ( ) , 0 ) ;
155
169
}
156
170
sum / N as f64
157
171
}
@@ -163,11 +177,8 @@ fn main() {
163
177
for y in 0 ..H {
164
178
let xx = x as f64 / W as f64 ;
165
179
let yy = y as f64 / H as f64 ;
166
- let ( nx, ny) = gradient ( xx, yy) ;
167
- let r = ( ( nx. min ( 0.5 ) . max ( -0.5 ) + 0.5 ) * 255.0 ) as u8 ;
168
- let g = ( ( ny. min ( 0.5 ) . max ( -0.5 ) + 0.5 ) * 255.0 ) as u8 ;
169
- // let brightness = min((sample(&mut rng, xx, yy) * 255.0) as u32, 255) as u8;
170
- img. put_pixel ( x, y, Rgb ( [ r, g, 0 ] ) ) ;
180
+ let brightness = min ( ( sample ( & mut rng, xx, yy) * 255.0 ) as u32 , 255 ) as u8 ;
181
+ img. put_pixel ( x, y, Rgb ( [ brightness, brightness, brightness] ) ) ;
171
182
}
172
183
}
173
184
img. save ( "out.png" ) . unwrap ( ) ;
0 commit comments