1+ use vec3:: * ;
2+
13use std;
24use std:: ops:: { Index , IndexMut } ;
35use std:: fs:: File ;
46use std:: path:: Path ;
57use std:: io:: Write ;
68
79use image;
10+ use image:: { Luma } ;
11+ use image:: math:: utils:: clamp;
12+
13+ use num:: { Float } ;
14+
15+ type Image32 = image:: ImageBuffer < Luma < f32 > , Vec < f32 > > ;
816
917pub struct RenderTarget {
1018 pub size : ( u32 , u32 ) ,
@@ -14,29 +22,39 @@ pub struct RenderTarget {
1422
1523impl RenderTarget {
1624 pub fn new ( size : ( u32 , u32 ) ) -> RenderTarget {
17- RenderTarget {
25+ RenderTarget {
1826 size : size,
1927 buf : vec ! [ [ 0.0 ; 3 ] ; ( size. 0 * size. 1 ) as usize ] ,
2028 samples : 0 ,
2129 }
2230 }
2331
24- pub fn write_png ( & self , filename : & str ) {
32+ #[ allow( dead_code) ]
33+ pub fn write_png ( & mut self , filename : & str ) {
2534 let ( nx, ny) = self . size ;
2635 let ns = self . samples ;
2736 let mut img = image:: DynamicImage :: new_rgb8 ( nx, ny) ;
37+ let bloom = self . bloom ( ) ;
2838
2939 for y in 0 ..ny {
3040 for x in 0 ..nx {
3141 let mut col = self [ ( x, y) ] . clone ( ) ;
32- col[ 0 ] = ( col[ 0 ] / ns as f64 ) . max ( 0.0 ) . min ( 1.0 ) . sqrt ( ) ;
33- col[ 1 ] = ( col[ 1 ] / ns as f64 ) . max ( 0.0 ) . min ( 1.0 ) . sqrt ( ) ;
34- col[ 2 ] = ( col[ 2 ] / ns as f64 ) . max ( 0.0 ) . min ( 1.0 ) . sqrt ( ) ;
42+
43+ for e in 0 ..3 {
44+ col[ e] /= ns as f64 ;
45+ col[ e] += bloom. get_pixel ( x, y) . data [ 0 ] as f64 ;
46+ col[ e] = clamp ( col[ e] , 0.0 , 1.0 ) ;
47+ col[ e] = col[ e] . sqrt ( ) ;
48+ }
49+
50+ // col[0] = clamp(col[0] / ns as f64, 0.0, 1.0).sqrt();
51+ // col[1] = clamp(col[1] / ns as f64, 0.0, 1.0).sqrt();
52+ // col[2] = clamp(col[2] / ns as f64, 0.0, 1.0).sqrt();
3553
3654 let ir = ( 255.99 * col[ 0 ] ) as u8 ;
3755 let ig = ( 255.99 * col[ 1 ] ) as u8 ;
3856 let ib = ( 255.99 * col[ 2 ] ) as u8 ;
39- img. as_mut_rgb8 ( ) . unwrap ( ) [ ( x, ny - y - 1 ) ]
57+ img. as_mut_rgb8 ( ) . unwrap ( ) [ ( x, y ) ]
4058 = image:: Rgb ( [ ir, ig, ib] ) ;
4159 }
4260 }
@@ -45,19 +63,38 @@ impl RenderTarget {
4563 }
4664
4765
66+ #[ allow( dead_code) ]
4867 pub fn write_hdr ( & self , filename : & str ) {
4968 let ref mut fout = File :: create ( & Path :: new ( filename) ) . unwrap ( ) ;
5069
51- let bytes = unsafe {
52- let ptr : * const u8 = std:: mem:: transmute ( & self . buf [ 0 ] [ 0 ] as * const _ ) ;
53- let len = 8 * self . size . 0 * self . size . 1 * 3 ;
54- std:: slice:: from_raw_parts ( ptr, len as usize )
70+ let bytes : & [ u8 ] = unsafe {
71+ let ptr : * const u8 = std:: mem:: transmute ( & self . buf [ 0 ] as * const _ ) ;
72+ std:: slice:: from_raw_parts ( ptr, ( 8 * self . size . 0 * self . size . 1 * 3 ) as usize )
5573 } ;
5674
5775 write ! ( fout, "{} {} {}\n \n " ,
5876 self . size. 0 , self . size. 1 , self . samples) . unwrap ( ) ;
5977 fout. write ( bytes) . unwrap ( ) ;
6078 }
79+
80+ fn bloom ( & mut self ) -> Image32 {
81+ let ( nx, ny) = self . size ;
82+
83+ let luma_matrix = vec3 ( 0.299 , 0.587 , 0.114 ) ;
84+
85+ let lumae : Vec < f32 > = self . buf . iter ( ) . map ( |p| {
86+ let mut l = 0.299 * p[ 0 ] + 0.587 * p[ 1 ] + 0.114 * p[ 2 ] ;
87+ l /= self . samples as f64 ;
88+ if l > 1.0 {
89+ l as f32
90+ } else {
91+ 0.0
92+ }
93+ } ) . collect ( ) ;
94+
95+ let im = Image32 :: from_vec ( nx, ny, lumae) . unwrap ( ) ;
96+ image:: imageops:: blur ( & im, 2.5 )
97+ }
6198}
6299
63100impl Index < ( u32 , u32 ) > for RenderTarget {
@@ -66,6 +103,7 @@ impl Index<(u32, u32)> for RenderTarget {
66103 & self . buf [ ( y * self . size . 0 + x) as usize ]
67104 }
68105}
106+
69107impl IndexMut < ( u32 , u32 ) > for RenderTarget {
70108 fn index_mut < ' a > ( & ' a mut self , ( x, y) : ( u32 , u32 ) ) -> & ' a mut [ f64 ; 3 ] {
71109 & mut self . buf [ ( y * self . size . 0 + x) as usize ]
0 commit comments