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