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