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