@@ -137,9 +137,9 @@ fn main() {
137137 println ! ( "let seed = {:?};" , seed) ;
138138 let mut rng : Rng = rand:: SeedableRng :: from_seed ( seed) ;
139139
140- let nx = 400 ;
141- let ny = 400 ;
142- let ns = 10000 ;
140+ let nx = 200 ;
141+ let ny = 200 ;
142+ let ns = 1000 ;
143143
144144 // let world : Vec<Box<Hitable>> = vec![
145145 // box Sphere{ center: vec3(0.0, 0.0, -1.0), radius: 0.5,
@@ -237,7 +237,7 @@ fn color(rng : &mut Rng, r0 : Ray, world : &Hitable) -> Vec3 {
237237 let mut attenuation = vec3 ( 1.0 , 1.0 , 1.0 ) ;
238238 let mut r = r0;
239239 for ttl in 0 ..50 {
240- match world. hit ( & r, ( 0.001 , f32:: INFINITY ) ) {
240+ match world. hit ( rng , & r, ( 0.001 , f32:: INFINITY ) ) {
241241 Some ( hit) => {
242242 let emitted = hit. material . emitted ( hit. uv , & hit. p ) ;
243243 accumulator += emitted * attenuation;
@@ -274,7 +274,7 @@ struct HitRecord<'a> {
274274}
275275
276276trait Hitable {
277- fn hit ( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > ;
277+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > ;
278278 fn bounding_box ( & self , time : ( f32 , f32 ) ) -> AABB ;
279279}
280280
@@ -311,7 +311,7 @@ fn stationary_sphere(radius : f32, center : Vec3, material : Rc<Material>) -> Sp
311311}
312312
313313impl Hitable for Sphere {
314- fn hit ( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
314+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
315315 let center = self . center ( r. time ) ;
316316 let oc = & r. origin - & center;
317317 let a = dot ( r. direction , r. direction ) ;
@@ -549,10 +549,10 @@ struct BVHNode {
549549}
550550
551551impl Hitable for BVHNode {
552- fn hit < ' a > ( & ' a self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
552+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
553553 if self . bbox . hit ( r, dist) {
554- let l_hit = self . left . hit ( r, dist) ;
555- let r_hit = self . right . hit ( r, dist) ;
554+ let l_hit = self . left . hit ( rng , r, dist) ;
555+ let r_hit = self . right . hit ( rng , r, dist) ;
556556 return match ( l_hit, r_hit) {
557557 ( None , h) => h,
558558 ( h, None ) => h,
@@ -821,7 +821,7 @@ macro_rules! aarect {
821821 }
822822
823823 impl Hitable for $XYRect {
824- fn hit( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option <HitRecord > {
824+ fn hit( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option <HitRecord > {
825825 let t = ( self . $z - r. origin[ $Z] ) / r. direction[ $Z] ;
826826 if !( dist. 0 < t && t < dist. 1 ) {
827827 return None ;
@@ -912,31 +912,42 @@ fn cornell_box(rng : &mut Rng) -> Box<Hitable> {
912912 let red : Rc < Material > = Rc :: new ( Lambertian ( ConstantTex ( vec3 ( 0.65 , 0.05 , 0.05 ) ) ) ) ;
913913 let white : Rc < Material > = Rc :: new ( Lambertian ( ConstantTex ( 0.73 * ONE3 ) ) ) ;
914914 let green : Rc < Material > = Rc :: new ( Lambertian ( ConstantTex ( vec3 ( 0.12 , 0.45 , 0.15 ) ) ) ) ;
915- let light : Rc < Material > = Rc :: new ( DiffuseLight ( ConstantTex ( 15 .0 * ONE3 ) ) ) ;
915+ let light : Rc < Material > = Rc :: new ( DiffuseLight ( ConstantTex ( 7 .0 * ONE3 ) ) ) ;
916916
917917 list. push ( YZRect :: new ( ( 0.0 , 555.0 ) , ( 0.0 , 555.0 ) , 555.0 , & green, true ) ) ;
918918 list. push ( YZRect :: new ( ( 0.0 , 555.0 ) , ( 0.0 , 555.0 ) , 0.0 , & red, false ) ) ;
919- list. push ( XZRect :: new ( ( 213 .0, 343 .0) , ( 227 .0, 332 .0) , 554.0 , & light, false ) ) ;
919+ list. push ( XZRect :: new ( ( 113 .0, 443 .0) , ( 127 .0, 432 .0) , 554.0 , & light, false ) ) ;
920920 list. push ( XZRect :: new ( ( 0.0 , 555.0 ) , ( 0.0 , 555.0 ) , 555.0 , & white, true ) ) ;
921921 list. push ( XZRect :: new ( ( 0.0 , 555.0 ) , ( 0.0 , 555.0 ) , 0.0 , & white, false ) ) ;
922922 list. push ( XYRect :: new ( ( 0.0 , 555.0 ) , ( 0.0 , 555.0 ) , 555.0 , & white, true ) ) ;
923923
924- list. push ( translate ( ivec3 ( 130 , 0 , 65 ) ,
925- rotate ( ivec3 ( 0 , 1 , 0 ) , -18.0 ,
926- cube ( ivec3 ( 0 , 0 , 0 ) , ivec3 ( 165 , 165 , 165 ) , & white) ) ) ) ;
927- list. push ( translate ( ivec3 ( 265 , 0 , 295 ) ,
928- rotate ( ivec3 ( 0 , 1 , 0 ) , 15.0 ,
929- cube ( ivec3 ( 0 , 0 , 0 ) , ivec3 ( 165 , 330 , 165 ) , & white) ) ) ) ;
924+ let b1 = translate ( ivec3 ( 130 , 1 , 65 ) ,
925+ rotate ( ivec3 ( 0 , 1 , 0 ) , -18.0 ,
926+ cube ( ivec3 ( 0 , 0 , 0 ) , ivec3 ( 165 , 165 , 165 ) , & white) ) ) ;
927+ let b2 = translate ( ivec3 ( 265 , 1 , 295 ) ,
928+ rotate ( ivec3 ( 0 , 1 , 0 ) , 15.0 ,
929+ cube ( ivec3 ( 0 , 0 , 0 ) , ivec3 ( 165 , 330 , 165 ) , & white) ) ) ;
930+
931+ list. push ( box ConstantMedium {
932+ boundary : b1,
933+ density : 0.01 ,
934+ phase_function : box Isotropic ( ConstantTex ( ivec3 ( 1 , 1 , 1 ) ) ) ,
935+ } ) ;
936+ list. push ( box ConstantMedium {
937+ boundary : b2,
938+ density : 0.01 ,
939+ phase_function : box Isotropic ( ConstantTex ( ivec3 ( 0 , 0 , 0 ) ) ) ,
940+ } ) ;
930941
931942 return into_bvh ( rng, list, ( 0.0 , 1.0 ) ) ;
932943}
933944
934945struct FlipNormals < H : Hitable > ( H ) ;
935946
936947impl < H : Hitable > Hitable for FlipNormals < H > {
937- fn hit ( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
948+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
938949 let FlipNormals ( ref inner) = * self ;
939- inner. hit ( r, dist) . map ( |mut hit| {
950+ inner. hit ( rng , r, dist) . map ( |mut hit| {
940951 hit. normal = -1.0 * hit. normal ;
941952 return hit;
942953 } )
@@ -972,10 +983,10 @@ fn translate(offset : Vec3, inner : Box<Hitable>) -> Box<Hitable> {
972983}
973984
974985impl Hitable for Translate {
975- fn hit ( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
986+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
976987 let mut r = ( * r) . clone ( ) ;
977988 r. origin -= self . offset ;
978- self . inner . hit ( & r, dist) . map ( |mut hit| {
989+ self . inner . hit ( rng , & r, dist) . map ( |mut hit| {
979990 hit. p += self . offset ;
980991 hit
981992 } )
@@ -1022,11 +1033,11 @@ fn rotate(axis : Vec3, angle : f32, inner : Box<Hitable>) -> Box<Hitable> {
10221033}
10231034
10241035impl Hitable for Rotate {
1025- fn hit ( & self , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
1036+ fn hit ( & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 ) ) -> Option < HitRecord > {
10261037 let mut r = ( * r) . clone ( ) ;
10271038 r. origin = self . mat * r. origin ;
10281039 r. direction = self . mat * r. direction ;
1029- self . inner . hit ( & r, dist) . map ( |mut hit| {
1040+ self . inner . hit ( rng , & r, dist) . map ( |mut hit| {
10301041 let inv = self . mat . transpose ( ) ;
10311042 hit. p = inv * hit. p ;
10321043 hit. normal = inv * hit. normal ;
@@ -1046,3 +1057,62 @@ impl Hitable for Rotate {
10461057 b
10471058 }
10481059}
1060+
1061+ struct ConstantMedium {
1062+ boundary : Box < Hitable > ,
1063+ density : f32 ,
1064+ phase_function : Box < Material > ,
1065+ }
1066+
1067+ impl Hitable for ConstantMedium {
1068+ fn hit (
1069+ & self , rng : & mut Rng , r : & Ray , dist : ( f32 , f32 )
1070+ ) -> Option < HitRecord > {
1071+ let mhit1 = self . boundary . hit ( rng, r, dist) ;
1072+ if let Some ( mut hit1) = mhit1 {
1073+ let mhit2 = self . boundary . hit ( rng, r, ( hit1. t + 0.0001 , dist. 1 ) ) ;
1074+ if let Some ( mut hit2) = mhit2 {
1075+ // assert!(hit1.t >= dist.0);
1076+ hit1. t = hit1. t . max ( dist. 0 ) ;
1077+ // assert!(hit2.t <= dist.1);
1078+ hit2. t = hit2. t . min ( dist. 1 ) ;
1079+ // assert!(hit1.t > hit2.t);
1080+ if hit1. t > hit2. t {
1081+ return None
1082+ }
1083+ hit1. t = hit1. t . max ( 0.0 ) ;
1084+
1085+ let dist_inside = ( hit2. t - hit1. t ) * r. direction . len ( ) ;
1086+ let hit_dist = -( rng. gen :: < f32 > ( ) . ln ( ) ) / self . density ;
1087+ if hit_dist < dist_inside {
1088+ let t = hit1. t + hit_dist / r. direction . len ( ) ;
1089+ let p = r. at ( t) ;
1090+ let normal = ivec3 ( 1 , 0 , 0 ) ;
1091+ return Some ( HitRecord {
1092+ t : t, p : p,
1093+ normal : normal, material : & * self . phase_function ,
1094+ uv : ( 0.0 , 0.0 ) ,
1095+ } )
1096+ }
1097+ }
1098+ }
1099+ return None
1100+ }
1101+
1102+ fn bounding_box ( & self , time : ( f32 , f32 ) ) -> AABB {
1103+ self . boundary . bounding_box ( time)
1104+ }
1105+ }
1106+
1107+ struct Isotropic < T : Texture > ( T ) ;
1108+
1109+ impl < T : Texture > Material for Isotropic < T > {
1110+ fn scatter (
1111+ & self , rng : & mut Rng , r_in : & Ray , hit : & HitRecord
1112+ ) -> Option < ( Ray , Vec3 ) > {
1113+ let Isotropic ( ref albedo) = * self ;
1114+ let mut r = ( * r_in) . clone ( ) ;
1115+ r. direction = rand_in_ball ( rng) . unit ( ) ;
1116+ Some ( ( r, albedo. tex_lookup ( hit. uv , & hit. p ) ) )
1117+ }
1118+ }
0 commit comments