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
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 ;
19 GLSL-SHADER-FILE: window-vertex-shader vertex-shader "window.v.glsl"
21 GLSL-SHADER-FILE: sobel-fragment-shader fragment-shader "sobel.f.glsl"
22 GLSL-PROGRAM: sobel-program
23 window-vertex-shader sobel-fragment-shader ;
25 GLSL-SHADER-FILE: loading-fragment-shader fragment-shader "loading.f.glsl"
26 GLSL-PROGRAM: loading-program
27 window-vertex-shader loading-fragment-shader ;
46 TUPLE: bunny-world < wasd-world
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
56 SPECIALIZED-VECTOR: bunny-vertex-struct
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 } ;
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 } ;
72 UNIFORM-TUPLE: loading-uniforms
73 { "texcoord-scale" vec2-uniform f }
74 { "loading-texture" texture-uniform f } ;
76 : numbers ( str -- seq )
77 " " split [ string>number ] map sift ;
79 : <bunny-vertex> ( vertex -- struct )
80 bunny-vertex-struct <struct>
81 swap >float-array >>vertex ; inline
83 : (parse-bunny-model) ( vs is -- vs is )
86 { [ dup length 5 = ] [ 3 head <bunny-vertex> pick push ] }
87 { [ dup first 3 = ] [ rest over push-all ] }
89 } cond (parse-bunny-model)
92 : parse-bunny-model ( -- vertexes indexes )
93 100000 <bunny-vertex-struct-vector>
97 : normal ( vertexes -- normal )
98 [ [ second ] [ first ] bi v- ]
99 [ [ third ] [ first ] bi v- ] bi cross
100 vneg normalize ; inline
102 : calc-bunny-normal ( vertexes indexes -- )
104 [ [ nth vertex>> ] curry { } map-as normal ]
105 [ [ nth [ v+ ] change-normal drop ] curry with each ] 2bi ;
107 : calc-bunny-normals ( vertexes indexes -- )
109 [ calc-bunny-normal ] with each ;
111 : normalize-bunny-normals ( vertexes -- )
112 [ [ normalize ] change-normal drop ] each ;
114 : bunny-data ( filename -- vertexes indexes )
115 ascii [ parse-bunny-model ] with-file-reader
116 [ calc-bunny-normals ]
117 [ drop normalize-bunny-normals ]
120 : <bunny-buffers> ( vertexes indexes -- vertex-buffer index-buffer index-count )
121 [ underlying>> static-upload draw-usage vertex-buffer byte-array>buffer ]
123 [ underlying>> static-upload draw-usage index-buffer byte-array>buffer ]
127 : bunny-model-path ( -- path ) "bun_zipper.ply" temp-file ;
129 CONSTANT: bunny-model-url "http://factorcode.org/bun_zipper.ply"
131 : download-bunny ( -- path )
132 bunny-model-path dup exists? [
133 bunny-model-url dup print flush
137 : get-bunny-data ( bunny-state -- )
138 download-bunny bunny-data
139 [ >>vertexes ] [ >>indexes ] bi* drop ;
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 ]
145 [ uint-indexes <index-elements> >>index-elements ] tri*
148 : <bunny-state> ( -- bunny-state )
150 dup [ get-bunny-data ] curry "Downloading bunny model" spawn drop ;
152 : bunny-loaded? ( bunny-state -- ? )
153 { [ vertexes>> ] [ indexes>> ] } 1&& ;
155 : bunny-state-filled? ( bunny-state -- ? )
156 { [ vertex-array>> ] [ index-elements>> ] } 1&& ;
158 : <sobel-state> ( window-vertex-buffer -- sobel-state )
160 swap sobel-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
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
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 ;
184 : <loading-state> ( window-vertex-buffer -- loading-state )
187 loading-program <program-instance> window-vertex buffer>vertex-array >>vertex-array
189 RGBA ubyte-components T{ texture-parameters
190 { wrap clamp-texcoord-to-edge }
191 { min-filter filter-linear }
192 { min-mipmap-filter f }
194 dup 0 "vocab:gpu/demos/bunny/loading.tiff" load-image allocate-texture-image
197 BEFORE: bunny-world begin-world
200 { -0.2 0.13 0.1 } 1.1 0.2 set-wasd-view
202 <bunny-state> >>bunny
203 <window-vertex-buffer>
204 [ <sobel-state> >>sobel ]
205 [ <loading-state> >>loading ] bi
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
217 : draw-bunny ( world -- )
218 T{ depth-state { comparison cmp-less } } set-gpu-state
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 }
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
237 : <sobel-uniforms> ( sobel -- uniforms )
239 [ color-texture>> ] [ normal-texture>> ] [ depth-texture>> ] tri
240 { 0.1 0.0 0.1 1.0 } ! line_color
243 : draw-sobel ( world -- )
244 T{ depth-state { comparison f } } set-gpu-state
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 ;
253 : draw-sobeled-bunny ( world -- )
254 [ draw-bunny ] [ draw-sobel ] bi ;
256 : draw-loading ( world -- )
257 T{ depth-state { comparison f } } set-gpu-state
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 ;
266 M: bunny-world draw-world*
269 dup bunny-state-filled? [ drop ] [ fill-bunny-state ] if
271 ] [ drop draw-loading ] if ;
273 AFTER: bunny-world resize-world
274 [ sobel>> framebuffer>> ] [ dim>> ] bi resize-framebuffer ;
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 ;
282 : bunny-window ( -- )
284 f T{ world-attributes
285 { world-class bunny-world }
287 { pixel-format-attributes {
290 T{ depth-bits { value 24 } }