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