]> gitweb.factorcode.org Git - factor.git/blob - extra/gpu/demos/bunny/bunny.factor
Factor source files should not be executable
[factor.git] / extra / gpu / demos / bunny / bunny.factor
1 ! (c)2009 Joe Groff bsd license
2 USING: accessors alien.c-types arrays classes.struct combinators
3 combinators.short-circuit game.worlds gpu gpu.buffers
4 gpu.util.wasd gpu.framebuffers gpu.render gpu.shaders gpu.state
5 gpu.textures gpu.util grouping http.client images images.loader
6 io io.encodings.ascii io.files io.files.temp kernel locals math
7 math.matrices math.vectors.simd math.parser math.vectors
8 method-chains namespaces sequences splitting threads ui ui.gadgets
9 ui.gadgets.worlds ui.pixel-formats specialized-arrays
10 specialized-vectors ;
11 FROM: alien.c-types => float ;
12 SPECIALIZED-ARRAY: float
13 SPECIALIZED-VECTOR: uint
14 SIMD: float
15 IN: gpu.demos.bunny
16
17 GLSL-SHADER-FILE: bunny-vertex-shader vertex-shader "bunny.v.glsl"
18 GLSL-SHADER-FILE: bunny-fragment-shader fragment-shader "bunny.f.glsl"
19 GLSL-PROGRAM: bunny-program
20     bunny-vertex-shader bunny-fragment-shader ;
21
22 GLSL-SHADER-FILE: window-vertex-shader vertex-shader "window.v.glsl"
23
24 GLSL-SHADER-FILE: sobel-fragment-shader fragment-shader "sobel.f.glsl"
25 GLSL-PROGRAM: sobel-program
26     window-vertex-shader sobel-fragment-shader ;
27
28 GLSL-SHADER-FILE: loading-fragment-shader fragment-shader "loading.f.glsl"
29 GLSL-PROGRAM: loading-program
30     window-vertex-shader loading-fragment-shader ;
31
32 TUPLE: bunny-state
33     vertexes
34     indexes
35     vertex-array
36     index-elements ;
37
38 TUPLE: sobel-state
39     vertex-array
40     color-texture
41     normal-texture
42     depth-texture
43     framebuffer ;
44
45 TUPLE: loading-state
46     vertex-array
47     texture ;
48
49 TUPLE: bunny-world < wasd-world
50     bunny sobel loading ;
51
52 VERTEX-FORMAT: bunny-vertex
53     { "vertex" float-components 3 f }
54     { f        float-components 1 f }
55     { "normal" float-components 3 f }
56     { f        float-components 1 f } ;
57
58 STRUCT: bunny-vertex-struct
59     { vertex float-4 }
60     { normal float-4 } ;
61
62 SPECIALIZED-VECTOR: bunny-vertex-struct
63
64 UNIFORM-TUPLE: bunny-uniforms < mvp-uniforms
65     { "light-position" vec3-uniform  f }
66     { "color"          vec4-uniform  f }
67     { "ambient"        vec4-uniform  f }
68     { "diffuse"        vec4-uniform  f }
69     { "shininess"      float-uniform f } ;
70
71 UNIFORM-TUPLE: sobel-uniforms
72     { "texcoord-scale" vec2-uniform    f }
73     { "color-texture"  texture-uniform f }
74     { "normal-texture" texture-uniform f }
75     { "depth-texture"  texture-uniform f }
76     { "line-color"     vec4-uniform    f } ; 
77
78 UNIFORM-TUPLE: loading-uniforms
79     { "texcoord-scale"  vec2-uniform    f }
80     { "loading-texture" texture-uniform f } ;
81
82 : numbers ( tokens -- seq )
83     [ string>number ] map ; inline
84
85 : <bunny-vertex> ( vertex -- struct )
86     bunny-vertex-struct <struct>
87         swap first3 0.0 float-4-boa >>vertex ; inline
88
89 : (read-line-tokens) ( seq stream -- seq )
90     " \n" over stream-read-until
91     [ [ pick push ] unless-empty ]
92     [
93         {
94             { CHAR: \s [ (read-line-tokens) ] }
95             { CHAR: \n [ drop ] }
96             [ 2drop [ f ] when-empty ]
97         } case
98     ] bi* ; inline recursive
99
100 : stream-read-line-tokens ( stream -- seq )
101     V{ } clone swap (read-line-tokens) ;
102
103 : each-line-tokens ( quot -- )
104     input-stream get [ stream-read-line-tokens ] curry each-morsel ; inline
105
106 : (parse-bunny-model) ( vs is -- vs is )
107     [
108         numbers {
109             { [ dup length 5 = ] [ <bunny-vertex> pick push ] }
110             { [ dup first 3 = ] [ rest append! ] }
111             [ drop ]
112         } cond
113     ] each-line-tokens ; inline
114
115 : parse-bunny-model ( -- vertexes indexes )
116     100000 <bunny-vertex-struct-vector>
117     100000 <uint-vector>
118     (parse-bunny-model) ; inline
119
120 :: normal ( a b c -- normal )
121     c a v-
122     b a v- cross normalize ; inline
123
124 :: calc-bunny-normal ( a b c vertexes -- )
125     a b c [ vertexes nth vertex>> ] tri@ normal :> n
126     a b c [ vertexes nth [ n v+ ] change-normal drop ] tri@ ; inline
127
128 : calc-bunny-normals ( vertexes indexes -- )
129     3 <sliced-groups> swap
130     [ [ first3 ] dip calc-bunny-normal ] curry each ; inline
131
132 : normalize-bunny-normals ( vertexes -- )
133     [ [ normalize ] change-normal drop ] each ; inline
134
135 : bunny-data ( filename -- vertexes indexes )
136     ascii [ parse-bunny-model ] with-file-reader
137     [ calc-bunny-normals ]
138     [ drop normalize-bunny-normals ]
139     [ ] 2tri ;
140
141 : <bunny-buffers> ( vertexes indexes -- vertex-buffer index-buffer index-count )
142     [ underlying>> static-upload draw-usage vertex-buffer byte-array>buffer ]
143     [
144         [ underlying>> static-upload draw-usage index-buffer  byte-array>buffer ]
145         [ length ] bi
146     ] bi* ;
147
148 : bunny-model-path ( -- path ) "bun_zipper.ply" temp-file ;
149
150 CONSTANT: bunny-model-url "http://factorcode.org/bun_zipper.ply"
151
152 : download-bunny ( -- path )
153     bunny-model-path dup exists? [
154         bunny-model-url dup print flush
155         over download-to
156     ] unless ;
157
158 : get-bunny-data ( bunny-state -- )
159     download-bunny bunny-data
160     [ >>vertexes ] [ >>indexes ] bi* drop ;
161
162 : fill-bunny-state ( bunny-state -- )
163     dup [ vertexes>> ] [ indexes>> ] bi <bunny-buffers>
164     [ bunny-program <program-instance> bunny-vertex buffer>vertex-array >>vertex-array ]
165     [ 0 <buffer-ptr> ]
166     [ uint-indexes <index-elements> >>index-elements ] tri*
167     drop ;
168
169 : <bunny-state> ( -- bunny-state )
170     bunny-state new
171     dup [ get-bunny-data ] curry "Downloading bunny model" spawn drop ;
172
173 : bunny-loaded? ( bunny-state -- ? )
174     { [ vertexes>> ] [ indexes>> ] } 1&& ;
175
176 : bunny-state-filled? ( bunny-state -- ? )
177     { [ vertex-array>> ] [ index-elements>> ] } 1&& ;
178
179 : <sobel-state> ( window-vertex-buffer -- sobel-state )
180     sobel-state new
181         swap sobel-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
182
183         RGBA half-components T{ texture-parameters
184             { wrap clamp-texcoord-to-edge }
185             { min-filter filter-linear }
186             { min-mipmap-filter f }
187         } <texture-2d> >>color-texture
188         RGBA half-components T{ texture-parameters
189             { wrap clamp-texcoord-to-edge }
190             { min-filter filter-linear }
191             { min-mipmap-filter f }
192         } <texture-2d> >>normal-texture
193         DEPTH u-24-components T{ texture-parameters
194             { wrap clamp-texcoord-to-edge }
195             { min-filter filter-linear }
196             { min-mipmap-filter f }
197         } <texture-2d> >>depth-texture
198
199         dup
200         [
201             [ color-texture>>  0 <texture-2d-attachment> ]
202             [ normal-texture>> 0 <texture-2d-attachment> ] bi 2array
203         ] [ depth-texture>> 0 <texture-2d-attachment> ] bi f { 1024 768 } <framebuffer> >>framebuffer ;
204
205 : <loading-state> ( window-vertex-buffer -- loading-state )
206     loading-state new
207         swap
208         loading-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
209
210         RGBA ubyte-components T{ texture-parameters
211             { wrap clamp-texcoord-to-edge }
212             { min-filter filter-linear }
213             { min-mipmap-filter f }
214         } <texture-2d>
215         dup 0 "vocab:gpu/demos/bunny/loading.tiff" load-image allocate-texture-image
216         >>texture ;
217
218 BEFORE: bunny-world begin-world
219     init-gpu
220     
221     { -0.2 0.13 0.1 } 1.1 0.2 set-wasd-view
222
223     <bunny-state> >>bunny
224     <window-vertex-buffer>
225     [ <sobel-state> >>sobel ]
226     [ <loading-state> >>loading ] bi
227     drop ;
228
229 : <bunny-uniforms> ( world -- uniforms )
230     [ wasd-mv-matrix ] [ wasd-p-matrix ] bi
231     { -10000.0 10000.0 10000.0 } ! light position
232     { 0.6 0.5 0.5 1.0 } ! color
233     { 0.2 0.2 0.2 0.2 } ! ambient
234     { 0.8 0.8 0.8 0.8 } ! diffuse
235     100.0 ! shininess
236     bunny-uniforms boa ;
237
238 : draw-bunny ( world -- )
239     T{ depth-state { comparison cmp-less } } set-gpu-state
240     
241     [
242         sobel>> framebuffer>> {
243             { T{ color-attachment f 0 } { 0.15 0.15 0.15 1.0 } }
244             { T{ color-attachment f 1 } { 0.0 0.0 0.0 0.0 } }
245             { depth-attachment 1.0 }
246         } clear-framebuffer
247     ] [
248         {
249             { "primitive-mode"     [ drop triangles-mode ] }
250             { "output-attachments" [ drop { T{ color-attachment f 0 } T{ color-attachment f 1 } } ] }
251             { "uniforms"           [ <bunny-uniforms> ] }
252             { "vertex-array"       [ bunny>> vertex-array>> ] }
253             { "indexes"            [ bunny>> index-elements>> ] }
254             { "framebuffer"        [ sobel>> framebuffer>> ] }
255         } <render-set> render
256     ] bi ;
257
258 : <sobel-uniforms> ( sobel -- uniforms )
259     { 1.0 1.0 } swap
260     [ color-texture>> ] [ normal-texture>> ] [ depth-texture>> ] tri
261     { 0.1 0.0 0.1 1.0 } ! line_color
262     sobel-uniforms boa ;
263
264 : draw-sobel ( world -- )
265     T{ depth-state { comparison f } } set-gpu-state
266
267     sobel>> {
268         { "primitive-mode" [ drop triangle-strip-mode ] }
269         { "indexes"        [ drop T{ index-range f 0 4 } ] }
270         { "uniforms"       [ <sobel-uniforms> ] }
271         { "vertex-array"   [ vertex-array>> ] }
272     } <render-set> render ;
273
274 : draw-sobeled-bunny ( world -- )
275     [ draw-bunny ] [ draw-sobel ] bi ;
276
277 : draw-loading ( world -- )
278     T{ depth-state { comparison f } } set-gpu-state
279
280     loading>> {
281         { "primitive-mode" [ drop triangle-strip-mode ] }
282         { "indexes"        [ drop T{ index-range f 0 4 } ] }
283         { "uniforms"       [ { 1.0 -1.0 } swap texture>> loading-uniforms boa ] }
284         { "vertex-array"   [ vertex-array>> ] }
285     } <render-set> render ;
286
287 M: bunny-world draw-world*
288     dup bunny>>
289     dup bunny-loaded? [
290         dup bunny-state-filled? [ drop ] [ fill-bunny-state ] if
291         draw-sobeled-bunny
292     ] [ drop draw-loading ] if ;
293
294 AFTER: bunny-world resize-world
295     [ sobel>> framebuffer>> ] [ dim>> ] bi resize-framebuffer ;
296
297 M: bunny-world pref-dim* drop { 1024 768 } ;
298 M: bunny-world tick-length drop 1000000 30 /i ;
299 M: bunny-world wasd-movement-speed drop 1/160. ;
300 M: bunny-world wasd-near-plane drop 1/32. ;
301 M: bunny-world wasd-far-plane drop 256.0 ;
302
303 : bunny-window ( -- )
304     [
305         f T{ world-attributes
306             { world-class bunny-world }
307             { title "Bunny" }
308             { pixel-format-attributes {
309                 windowed
310                 double-buffered
311                 T{ depth-bits { value 24 } }
312             } }
313             { grab-input? t }
314         } open-window
315     ] with-ui ;
316
317 MAIN: bunny-window