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
11 FROM: alien.c-types => float ;
12 SPECIALIZED-ARRAY: float
13 SPECIALIZED-VECTOR: uint
16 GLSL-SHADER-FILE: bunny-vertex-shader vertex-shader "bunny.v.glsl"
17 GLSL-SHADER-FILE: bunny-fragment-shader fragment-shader "bunny.f.glsl"
18 GLSL-PROGRAM: bunny-program
19 bunny-vertex-shader bunny-fragment-shader ;
21 GLSL-SHADER-FILE: window-vertex-shader vertex-shader "window.v.glsl"
23 GLSL-SHADER-FILE: sobel-fragment-shader fragment-shader "sobel.f.glsl"
24 GLSL-PROGRAM: sobel-program
25 window-vertex-shader sobel-fragment-shader ;
27 GLSL-SHADER-FILE: loading-fragment-shader fragment-shader "loading.f.glsl"
28 GLSL-PROGRAM: loading-program
29 window-vertex-shader loading-fragment-shader ;
48 TUPLE: bunny-world < wasd-world
51 VERTEX-FORMAT: bunny-vertex
52 { "vertex" float-components 3 f }
53 { f float-components 1 f }
54 { "normal" float-components 3 f }
55 { f float-components 1 f } ;
57 STRUCT: bunny-vertex-struct
61 SPECIALIZED-VECTOR: bunny-vertex-struct
63 UNIFORM-TUPLE: bunny-uniforms < mvp-uniforms
64 { "light-position" vec3-uniform f }
65 { "color" vec4-uniform f }
66 { "ambient" vec4-uniform f }
67 { "diffuse" vec4-uniform f }
68 { "shininess" float-uniform f } ;
70 UNIFORM-TUPLE: sobel-uniforms
71 { "texcoord-scale" vec2-uniform f }
72 { "color-texture" texture-uniform f }
73 { "normal-texture" texture-uniform f }
74 { "depth-texture" texture-uniform f }
75 { "line-color" vec4-uniform f } ;
77 UNIFORM-TUPLE: loading-uniforms
78 { "texcoord-scale" vec2-uniform f }
79 { "loading-texture" texture-uniform f } ;
81 : numbers ( tokens -- seq )
82 [ string>number ] map ; inline
84 : <bunny-vertex> ( vertex -- struct )
85 bunny-vertex-struct <struct>
86 swap first3 0.0 float-4-boa >>vertex ; inline
88 : (read-line-tokens) ( seq stream -- seq )
89 " \n" over stream-read-until
90 [ [ pick push ] unless-empty ]
93 { CHAR: \s [ (read-line-tokens) ] }
95 [ 2drop [ f ] when-empty ]
97 ] bi* ; inline recursive
99 : stream-read-line-tokens ( stream -- seq )
100 V{ } clone swap (read-line-tokens) ;
102 : each-line-tokens ( quot -- )
103 input-stream get [ stream-read-line-tokens ] curry each-morsel ; inline
105 : (parse-bunny-model) ( vs is -- vs is )
108 { [ dup length 5 = ] [ <bunny-vertex> pick push ] }
109 { [ dup first 3 = ] [ rest append! ] }
112 ] each-line-tokens ; inline
114 : parse-bunny-model ( -- vertexes indexes )
115 100000 <bunny-vertex-struct-vector>
117 (parse-bunny-model) ; inline
119 :: normal ( a b c -- normal )
121 b a v- cross normalize ; inline
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
127 : calc-bunny-normals ( vertexes indexes -- )
128 3 <sliced-groups> swap
129 [ [ first3 ] dip calc-bunny-normal ] curry each ; inline
131 : normalize-bunny-normals ( vertexes -- )
132 [ [ normalize ] change-normal drop ] each ; inline
134 : bunny-data ( filename -- vertexes indexes )
135 ascii [ parse-bunny-model ] with-file-reader
136 [ calc-bunny-normals ]
137 [ drop normalize-bunny-normals ]
140 : <bunny-buffers> ( vertexes indexes -- vertex-buffer index-buffer index-count )
141 [ underlying>> static-upload draw-usage vertex-buffer byte-array>buffer ]
143 [ underlying>> static-upload draw-usage index-buffer byte-array>buffer ]
147 : bunny-model-path ( -- path ) "bun_zipper.ply" temp-file ;
149 CONSTANT: bunny-model-url "http://factorcode.org/bun_zipper.ply"
151 : download-bunny ( -- path )
152 bunny-model-path dup exists? [
153 bunny-model-url dup print flush
157 : get-bunny-data ( bunny-state -- )
158 download-bunny bunny-data
159 [ >>vertexes ] [ >>indexes ] bi* drop ;
161 : fill-bunny-state ( bunny-state -- )
162 dup [ vertexes>> ] [ indexes>> ] bi <bunny-buffers>
163 [ bunny-program <program-instance> bunny-vertex buffer>vertex-array >>vertex-array ]
165 [ uint-indexes <index-elements> >>index-elements ] tri*
168 : <bunny-state> ( -- bunny-state )
170 dup [ get-bunny-data ] curry "Downloading bunny model" spawn drop ;
172 : bunny-loaded? ( bunny-state -- ? )
173 { [ vertexes>> ] [ indexes>> ] } 1&& ;
175 : bunny-state-filled? ( bunny-state -- ? )
176 { [ vertex-array>> ] [ index-elements>> ] } 1&& ;
178 : <sobel-state> ( window-vertex-buffer -- sobel-state )
180 swap sobel-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
182 RGBA half-components T{ texture-parameters
183 { wrap clamp-texcoord-to-edge }
184 { min-filter filter-linear }
185 { min-mipmap-filter f }
186 } <texture-2d> >>color-texture
187 RGBA half-components T{ texture-parameters
188 { wrap clamp-texcoord-to-edge }
189 { min-filter filter-linear }
190 { min-mipmap-filter f }
191 } <texture-2d> >>normal-texture
192 DEPTH u-24-components T{ texture-parameters
193 { wrap clamp-texcoord-to-edge }
194 { min-filter filter-linear }
195 { min-mipmap-filter f }
196 } <texture-2d> >>depth-texture
200 [ color-texture>> 0 <texture-2d-attachment> ]
201 [ normal-texture>> 0 <texture-2d-attachment> ] bi 2array
202 ] [ depth-texture>> 0 <texture-2d-attachment> ] bi f { 1024 768 } <framebuffer> >>framebuffer ;
204 : <loading-state> ( window-vertex-buffer -- loading-state )
207 loading-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
209 RGBA ubyte-components T{ texture-parameters
210 { wrap clamp-texcoord-to-edge }
211 { min-filter filter-linear }
212 { min-mipmap-filter f }
214 dup 0 "vocab:gpu/demos/bunny/loading.tiff" load-image allocate-texture-image
217 BEFORE: bunny-world begin-world
220 { -0.2 0.13 0.1 } 1.1 0.2 set-wasd-view
222 <bunny-state> >>bunny
223 <window-vertex-buffer>
224 [ <sobel-state> >>sobel ]
225 [ <loading-state> >>loading ] bi
228 : <bunny-uniforms> ( world -- uniforms )
229 [ wasd-mv-matrix ] [ wasd-p-matrix ] bi
230 { -10000.0 10000.0 10000.0 } ! light position
231 { 0.6 0.5 0.5 1.0 } ! color
232 { 0.2 0.2 0.2 0.2 } ! ambient
233 { 0.8 0.8 0.8 0.8 } ! diffuse
237 : draw-bunny ( world -- )
238 T{ depth-state { comparison cmp-less } } set-gpu-state
241 sobel>> framebuffer>> {
242 { T{ color-attachment f 0 } { 0.15 0.15 0.15 1.0 } }
243 { T{ color-attachment f 1 } { 0.0 0.0 0.0 0.0 } }
244 { depth-attachment 1.0 }
248 { "primitive-mode" [ drop triangles-mode ] }
249 { "output-attachments" [ drop { T{ color-attachment f 0 } T{ color-attachment f 1 } } ] }
250 { "uniforms" [ <bunny-uniforms> ] }
251 { "vertex-array" [ bunny>> vertex-array>> ] }
252 { "indexes" [ bunny>> index-elements>> ] }
253 { "framebuffer" [ sobel>> framebuffer>> ] }
254 } <render-set> render
257 : <sobel-uniforms> ( sobel -- uniforms )
259 [ color-texture>> ] [ normal-texture>> ] [ depth-texture>> ] tri
260 { 0.1 0.0 0.1 1.0 } ! line_color
263 : draw-sobel ( world -- )
264 T{ depth-state { comparison f } } set-gpu-state
267 { "primitive-mode" [ drop triangle-strip-mode ] }
268 { "indexes" [ drop T{ index-range f 0 4 } ] }
269 { "uniforms" [ <sobel-uniforms> ] }
270 { "vertex-array" [ vertex-array>> ] }
271 } <render-set> render ;
273 : draw-sobeled-bunny ( world -- )
274 [ draw-bunny ] [ draw-sobel ] bi ;
276 : draw-loading ( world -- )
277 T{ depth-state { comparison f } } set-gpu-state
280 { "primitive-mode" [ drop triangle-strip-mode ] }
281 { "indexes" [ drop T{ index-range f 0 4 } ] }
282 { "uniforms" [ { 1.0 -1.0 } swap texture>> loading-uniforms boa ] }
283 { "vertex-array" [ vertex-array>> ] }
284 } <render-set> render ;
286 M: bunny-world draw-world*
289 dup bunny-state-filled? [ drop ] [ fill-bunny-state ] if
291 ] [ drop draw-loading ] if ;
293 AFTER: bunny-world resize-world
294 [ sobel>> framebuffer>> ] [ dim>> ] bi resize-framebuffer ;
296 M: bunny-world pref-dim* drop { 1024 768 } ;
297 M: bunny-world tick-length drop 1000 30 /i ;
298 M: bunny-world wasd-movement-speed drop 1/160. ;
299 M: bunny-world wasd-near-plane drop 1/32. ;
300 M: bunny-world wasd-far-plane drop 256.0 ;
302 : bunny-window ( -- )
304 f T{ world-attributes
305 { world-class bunny-world }
307 { pixel-format-attributes {
310 T{ depth-bits { value 24 } }