]> gitweb.factorcode.org Git - factor.git/blob - extra/benchmark/raytracer-simd/raytracer-simd.factor
Merge branch 'a7a39d3766624227966bca34f0778030592d82c2' of git://github.com/prunedtre...
[factor.git] / extra / benchmark / raytracer-simd / raytracer-simd.factor
1 ! Factor port of the raytracer benchmark from
2 ! http://www.ffconsultancy.com/free/ray_tracer/languages.html
3
4 USING: arrays accessors io io.files io.files.temp
5 io.encodings.binary kernel math math.constants math.functions
6 math.vectors math.vectors.simd math.parser make sequences
7 sequences.private words hints classes.struct ;
8 QUALIFIED-WITH: alien.c-types c
9 SIMD: c:double
10 IN: benchmark.raytracer-simd
11
12 ! parameters
13
14 ! Normalized { -1 -3 2 }.
15 CONSTANT: light
16     double-4{
17         -0.2672612419124244
18         -0.8017837257372732
19         0.5345224838248488
20         0.0
21     }
22
23 CONSTANT: oversampling 4
24
25 CONSTANT: levels 3
26
27 CONSTANT: size 200
28
29 : delta ( -- n ) epsilon sqrt ; inline
30
31 TUPLE: ray { orig double-4 read-only } { dir double-4 read-only } ;
32
33 C: <ray> ray
34
35 TUPLE: hit { normal double-4 read-only } { lambda float read-only } ;
36
37 C: <hit> hit
38
39 GENERIC: intersect-scene ( hit ray scene -- hit )
40
41 TUPLE: sphere { center double-4 read-only } { radius float read-only } ;
42
43 C: <sphere> sphere
44
45 : sphere-v ( sphere ray -- v )
46     [ center>> ] [ orig>> ] bi* v- ; inline
47
48 : sphere-b ( v ray -- b )
49     dir>> v. ; inline
50
51 : sphere-d ( sphere b v -- d )
52     [ radius>> sq ] [ sq ] [ norm-sq ] tri* - + ; inline
53
54 : -+ ( x y -- x-y x+y )
55     [ - ] [ + ] 2bi ; inline
56
57 : sphere-t ( b d -- t )
58     -+ dup 0.0 <
59     [ 2drop 1/0. ] [ [ [ 0.0 > ] keep ] dip ? ] if ; inline
60
61 : sphere-b&v ( sphere ray -- b v )
62     [ sphere-v ] [ nip ] 2bi
63     [ sphere-b ] [ drop ] 2bi ; inline
64
65 : ray-sphere ( sphere ray -- t )
66     [ drop ] [ sphere-b&v ] 2bi
67     [ drop ] [ sphere-d ] 3bi
68     dup 0.0 < [ 3drop 1/0. ] [ sqrt sphere-t nip ] if ; inline
69
70 : if-ray-sphere ( hit ray sphere quot -- hit )
71     #! quot: hit ray sphere l -- hit
72     [
73         [ ] [ swap ray-sphere nip ] [ 2drop lambda>> ] 3tri
74         [ drop ] [ < ] 2bi
75     ] dip [ 3drop ] if ; inline
76
77 : sphere-n ( ray sphere l -- n )
78     [ [ orig>> ] [ dir>> ] bi ] [ center>> ] [ ] tri*
79     swap [ v*n ] dip v- v+ ; inline
80
81 M: sphere intersect-scene ( hit ray sphere -- hit )
82     [ [ sphere-n normalize ] keep <hit> nip ] if-ray-sphere ;
83
84 HINTS: M\ sphere intersect-scene { hit ray sphere } ;
85
86 TUPLE: group < sphere { objs array read-only } ;
87
88 : <group> ( objs bound -- group )
89     [ center>> ] [ radius>> ] bi rot group boa ; inline
90
91 : make-group ( bound quot -- )
92     swap [ { } make ] dip <group> ; inline
93
94 M: group intersect-scene ( hit ray group -- hit )
95     [ drop objs>> [ intersect-scene ] with each ] if-ray-sphere ;
96
97 HINTS: M\ group intersect-scene { hit ray group } ;
98
99 CONSTANT: initial-hit T{ hit f double-4{ 0.0 0.0 0.0 0.0 } 1/0. }
100
101 : initial-intersect ( ray scene -- hit )
102     [ initial-hit ] 2dip intersect-scene ; inline
103
104 : ray-o ( ray hit -- o )
105     [ [ orig>> ] [ normal>> delta v*n ] bi* ]
106     [ [ dir>> ] [ lambda>> ] bi* v*n ]
107     2bi v+ v+ ; inline
108
109 : sray-intersect ( ray scene hit -- ray )
110     swap [ ray-o light vneg <ray> ] dip initial-intersect ; inline
111
112 : ray-g ( hit -- g ) normal>> light v. ; inline
113
114 : cast-ray ( ray scene -- g )
115     2dup initial-intersect dup lambda>> 1/0. = [
116         3drop 0.0
117     ] [
118         [ sray-intersect lambda>> 1/0. = ] keep swap
119         [ ray-g neg ] [ drop 0.0 ] if
120     ] if ; inline
121
122 : create-center ( c r d -- c2 )
123     [ 3.0 12.0 sqrt / * ] dip n*v v+ ; inline
124
125 DEFER: create ( level c r -- scene )
126
127 : create-step ( level c r d -- scene )
128     over [ create-center ] dip 2.0 / [ 1 - ] 2dip create ;
129
130 : create-offsets ( quot -- )
131     {
132         double-4{ -1.0 1.0 -1.0 0.0 }
133         double-4{ 1.0 1.0 -1.0 0.0 }
134         double-4{ -1.0 1.0 1.0 0.0 }
135         double-4{ 1.0 1.0 1.0 0.0 }
136     } swap each ; inline
137
138 : create-bound ( c r -- sphere ) 3.0 * <sphere> ;
139
140 : create-group ( level c r -- scene )
141     2dup create-bound [
142         2dup <sphere> ,
143         [ [ 3dup ] dip create-step , ] create-offsets 3drop
144     ] make-group ;
145
146 : create ( level c r -- scene )
147     pick 1 = [ <sphere> nip ] [ create-group ] if ;
148
149 : ss-point ( dx dy -- point )
150     [ oversampling /f ] bi@ 0.0 0.0 double-4-boa ;
151
152 : ss-grid ( -- ss-grid )
153     oversampling [ oversampling [ ss-point ] with map ] map ;
154
155 : ray-grid ( point ss-grid -- ray-grid )
156     [
157         [ v+ normalize double-4{ 0.0 0.0 -4.0 0.0 } swap <ray> ] with map
158     ] with map ;
159
160 : ray-pixel ( scene point -- n )
161     ss-grid ray-grid [ 0.0 ] 2dip
162     [ [ swap cast-ray + ] with each ] with each ;
163
164 : pixel-grid ( -- grid )
165     size reverse [
166         size [
167             [ size 0.5 * - ] bi@ swap size
168             0.0 double-4-boa
169         ] with map
170     ] map ;
171
172 : pgm-header ( w h -- )
173     "P5\n" % swap # " " % # "\n255\n" % ;
174
175 : pgm-pixel ( n -- ) 255 * 0.5 + >fixnum , ;
176
177 : ray-trace ( scene -- pixels )
178     pixel-grid [ [ ray-pixel ] with map ] with map ;
179
180 : run ( -- string )
181     levels double-4{ 0.0 -1.0 0.0 0.0 } 1.0 create ray-trace [
182         size size pgm-header
183         [ [ oversampling sq / pgm-pixel ] each ] each
184     ] B{ } make ;
185
186 : raytracer-main ( -- )
187     run "raytracer.pnm" temp-file binary set-file-contents ;
188
189 MAIN: raytracer-main