1 ! Copyright (C) 2009 Joe Groff.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays audio.engine audio.loader game.loop
4 game.worlds gpu gpu.render gpu.shaders gpu.util gpu.util.wasd
5 kernel literals math math.libm math.matrices
6 math.matrices.extras math.order math.vectors method-chains
7 sequences ui.gadgets.worlds ui.pixel-formats ;
10 GLSL-SHADER-FILE: raytrace-vertex-shader vertex-shader "raytrace.v.glsl"
11 GLSL-SHADER-FILE: raytrace-fragment-shader fragment-shader "raytrace.f.glsl"
12 GLSL-PROGRAM: raytrace-program
13 raytrace-vertex-shader raytrace-fragment-shader
14 window-vertex-format ;
16 UNIFORM-TUPLE: sphere-uniforms
17 { "center" vec3-uniform f }
18 { "radius" float-uniform f }
19 { "color" vec4-uniform f } ;
21 UNIFORM-TUPLE: raytrace-uniforms
22 { "mv-inv-matrix" mat4-uniform f }
23 { "fov" vec2-uniform f }
25 { "spheres" sphere-uniforms 4 }
27 { "floor-height" float-uniform f }
28 { "floor-color" vec4-uniform 2 }
29 { "background-color" vec4-uniform f }
30 { "light-direction" vec3-uniform f } ;
32 CONSTANT: reflection-color { 1.0 0.0 1.0 0.0 }
40 { theta float initial: 0.0 } ;
42 TUPLE: raytrace-world < wasd-world
47 : tick-sphere ( sphere -- )
48 dup dtheta>> [ + ] curry change-theta drop ;
50 : sphere-center ( sphere -- center )
51 [ [ axis>> ] [ theta>> ] bi <rotation-matrix4> ]
54 M: sphere audio-position sphere-center ; inline
55 M: sphere audio-distance radius>> fsqrt 2.0 * ; inline
57 : <sphere-uniforms> ( world -- uniforms )
58 [ wasd-mv-inv-matrix ]
62 [ [ sphere-center ] [ radius>> ] [ color>> ] tri sphere-uniforms boa ] map
65 { { 1.0 0.0 0.0 1.0 } { 1.0 1.0 1.0 1.0 } } ! floor_color
66 { 0.15 0.15 1.0 1.0 } ! background_color
67 { 0.0 -1.0 -0.1 } ! light_direction
68 raytrace-uniforms boa ;
70 CONSTANT: initial-spheres {
71 T{ sphere f { 0.0 1.0 0.0 } { 0.0 0.0 0.0 } 0.0 4.0 $ reflection-color }
72 T{ sphere f { 0.0 1.0 0.0 } { 7.0 0.0 0.0 } 0.02 1.0 { 1.0 0.0 0.0 1.0 } }
73 T{ sphere f { 0.0 0.0 -1.0 } { -9.0 0.0 0.0 } 0.03 1.0 { 0.0 1.0 0.0 1.0 } }
74 T{ sphere f { 1.0 0.0 0.0 } { 0.0 5.0 0.0 } 0.025 1.0 { 1.0 1.0 0.0 1.0 } }
77 :: set-up-audio ( world -- )
78 world audio-engine>> :> audio-engine
79 world spheres>> :> spheres
81 audio-engine world >>listener update-audio
83 audio-engine spheres first
84 "vocab:gpu/demos/raytrace/mirror-ball.aiff" read-audio t <static-audio-clip>
85 audio-engine spheres second
86 "vocab:gpu/demos/raytrace/red-ball.aiff" read-audio t <static-audio-clip>
87 audio-engine spheres third
88 "vocab:gpu/demos/raytrace/green-ball.aiff" read-audio t <static-audio-clip>
89 audio-engine spheres fourth
90 "vocab:gpu/demos/raytrace/yellow-ball.aiff" read-audio t <static-audio-clip>
94 M: raytrace-world begin-game-world
96 { -2.0 6.25 10.0 } 0.19 0.55 set-wasd-view
97 initial-spheres [ clone ] map >>spheres
98 raytrace-program <program-instance> <window-vertex-array> >>vertex-array
103 AFTER: raytrace-world resize-world
104 dup dim>> dup first2 min >float v/n fov v*n >>fov drop ;
106 AFTER: raytrace-world tick-game-world
107 spheres>> [ tick-sphere ] each ;
109 M: raytrace-world draw-world*
111 { "primitive-mode" [ drop triangle-strip-mode ] }
112 { "indexes" [ drop T{ index-range f 0 4 } ] }
113 { "uniforms" [ <sphere-uniforms> ] }
114 { "vertex-array" [ vertex-array>> ] }
115 } <render-set> render ;
117 M: raytrace-world wasd-movement-speed drop 1/4. ;
119 GAME: raytrace-game {
120 { world-class raytrace-world }
121 { title "Raytracing" }
122 { pixel-format-attributes {
127 { use-game-input? t }
128 { use-audio-engine? t }
129 { pref-dim { 1024 768 } }
130 { tick-interval-nanos $[ 60 fps ] }