]> gitweb.factorcode.org Git - factor.git/blob - extra/spheres/spheres.factor
Merge branch 'fix-bloom-filters-test' of git://github.com/alec/factor
[factor.git] / extra / spheres / spheres.factor
1 USING: kernel opengl opengl.demo-support opengl.gl opengl.textures
2 opengl.shaders opengl.framebuffers opengl.capabilities multiline
3 ui.gadgets accessors sequences ui.render ui math locals arrays
4 generalizations combinators ui.gadgets.worlds
5 literals ui.pixel-formats ;
6 FROM: opengl.demo-support => rect-vertices ;
7 IN: spheres
8
9 STRING: plane-vertex-shader
10 varying vec3 object_position;
11 void
12 main()
13 {
14     object_position = gl_Vertex.xyz;
15     gl_Position = ftransform();
16 }
17 ;
18
19 STRING: plane-fragment-shader
20 uniform float checker_size_inv;
21 uniform vec4 checker_color_1, checker_color_2;
22 varying vec3 object_position;
23
24 bool
25 checker_color(vec3 p)
26 {
27     vec3 pprime = checker_size_inv * object_position;
28     return fract((floor(pprime.x) + floor(pprime.z)) * 0.5) == 0.0;
29 }
30
31 void
32 main()
33 {
34     float distance_factor = (gl_FragCoord.z * 0.5 + 0.5);
35     distance_factor = pow(distance_factor, 500.0)*0.5;
36     
37     gl_FragColor = checker_color(object_position)
38         ? mix(checker_color_1, checker_color_2, distance_factor)
39         : mix(checker_color_2, checker_color_1, distance_factor);
40 }
41 ;
42
43 STRING: sphere-vertex-shader
44 attribute vec3 center;
45 attribute float radius;
46 attribute vec4 surface_color;
47 varying float vradius;
48 varying vec3 sphere_position;
49 varying vec4 world_position, vcolor;
50
51 void
52 main()
53 {
54     world_position = gl_ModelViewMatrix * vec4(center, 1);
55     sphere_position = gl_Vertex.xyz;
56     
57     gl_Position = gl_ProjectionMatrix * (world_position + vec4(sphere_position * radius, 0));
58     
59     vcolor = surface_color;
60     vradius = radius;
61 }
62 ;
63
64 STRING: sphere-solid-color-fragment-shader
65 uniform vec3 light_position;
66 varying vec4 vcolor;
67
68 const vec4 ambient = vec4(0.25, 0.2, 0.25, 1.0);
69 const vec4 diffuse = vec4(0.75, 0.8, 0.75, 1.0);
70
71 vec4
72 sphere_color(vec3 point, vec3 normal)
73 {
74     vec3 transformed_light_position = (gl_ModelViewMatrix * vec4(light_position, 1)).xyz;
75     vec3 direction = normalize(transformed_light_position - point);
76     float d = max(0.0, dot(normal, direction));
77     
78     return ambient * vcolor + diffuse * vec4(d * vcolor.rgb, vcolor.a);
79 }
80 ;
81
82 STRING: sphere-texture-fragment-shader
83 uniform samplerCube surface_texture;
84
85 vec4
86 sphere_color(vec3 point, vec3 normal)
87 {
88     vec3 reflect = reflect(normalize(point), normal);
89     return textureCube(surface_texture, reflect * gl_NormalMatrix);
90 }
91 ;
92
93 STRING: sphere-main-fragment-shader
94 varying float vradius;
95 varying vec3 sphere_position;
96 varying vec4 world_position;
97
98 vec4 sphere_color(vec3 point, vec3 normal);
99
100 void
101 main()
102 {
103         float radius = length(sphere_position);
104         if(radius > 1.0) discard;
105         
106         vec3 surface = sphere_position + vec3(0.0, 0.0, sqrt(1.0 - radius*radius));
107         vec4 world_surface = world_position + vec4(surface * vradius, 0);
108         vec4 transformed_surface = gl_ProjectionMatrix * world_surface;
109         
110     gl_FragDepth = (transformed_surface.z/transformed_surface.w + 1.0) * 0.5;
111         gl_FragColor = sphere_color(world_surface.xyz, surface);
112 }
113 ;
114
115 TUPLE: spheres-world < demo-world
116     plane-program solid-sphere-program texture-sphere-program
117     reflection-framebuffer reflection-depthbuffer
118     reflection-texture ;
119
120 M: spheres-world near-plane ( gadget -- z )
121     drop 1.0 ;
122 M: spheres-world far-plane ( gadget -- z )
123     drop 512.0 ;
124 M: spheres-world distance-step ( gadget -- dz )
125     drop 0.5 ;
126
127 : (reflection-dim) ( -- w h )
128     512 512 ;
129
130 : (make-reflection-texture) ( -- texture )
131     gen-texture [
132         GL_TEXTURE_CUBE_MAP swap glBindTexture
133         GL_TEXTURE_CUBE_MAP GL_TEXTURE_MAG_FILTER GL_LINEAR glTexParameteri
134         GL_TEXTURE_CUBE_MAP GL_TEXTURE_MIN_FILTER GL_LINEAR glTexParameteri
135         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
136         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
137         GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_R GL_CLAMP glTexParameteri
138         ${
139             GL_TEXTURE_CUBE_MAP_POSITIVE_X
140             GL_TEXTURE_CUBE_MAP_POSITIVE_Y
141             GL_TEXTURE_CUBE_MAP_POSITIVE_Z
142             GL_TEXTURE_CUBE_MAP_NEGATIVE_X
143             GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
144             GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
145         }
146         [ 0 GL_RGBA8 (reflection-dim) 0 GL_RGBA GL_UNSIGNED_BYTE f glTexImage2D ]
147         each
148     ] keep ;
149
150 : (make-reflection-depthbuffer) ( -- depthbuffer )
151     gen-renderbuffer [
152         GL_RENDERBUFFER_EXT swap glBindRenderbufferEXT
153         GL_RENDERBUFFER_EXT GL_DEPTH_COMPONENT32 (reflection-dim) glRenderbufferStorageEXT
154     ] keep ;
155
156 : (make-reflection-framebuffer) ( depthbuffer -- framebuffer )
157     gen-framebuffer dup [
158         swap [ GL_FRAMEBUFFER_EXT GL_DEPTH_ATTACHMENT_EXT GL_RENDERBUFFER_EXT ] dip
159         glFramebufferRenderbufferEXT
160     ] with-framebuffer ;
161
162 : (plane-program) ( -- program )
163     plane-vertex-shader plane-fragment-shader <simple-gl-program> ;
164 : (solid-sphere-program) ( -- program )
165     sphere-vertex-shader <vertex-shader> check-gl-shader
166     sphere-solid-color-fragment-shader <fragment-shader> check-gl-shader
167     sphere-main-fragment-shader <fragment-shader> check-gl-shader
168     3array <gl-program> check-gl-program ;
169 : (texture-sphere-program) ( -- program )
170     sphere-vertex-shader <vertex-shader> check-gl-shader
171     sphere-texture-fragment-shader <fragment-shader> check-gl-shader
172     sphere-main-fragment-shader <fragment-shader> check-gl-shader
173     3array <gl-program> check-gl-program ;
174
175 M: spheres-world begin-world
176     "2.0" { "GL_ARB_shader_objects" } require-gl-version-or-extensions
177     { "GL_EXT_framebuffer_object" } require-gl-extensions
178     20.0 10.0 20.0 set-demo-orientation
179     (plane-program) >>plane-program
180     (solid-sphere-program) >>solid-sphere-program
181     (texture-sphere-program) >>texture-sphere-program
182     (make-reflection-texture) >>reflection-texture
183     (make-reflection-depthbuffer) [ >>reflection-depthbuffer ] keep
184     (make-reflection-framebuffer) >>reflection-framebuffer
185     drop ;
186
187 M: spheres-world end-world
188     {
189         [ reflection-framebuffer>> [ delete-framebuffer ] when* ]
190         [ reflection-depthbuffer>> [ delete-renderbuffer ] when* ]
191         [ reflection-texture>> [ delete-texture ] when* ]
192         [ solid-sphere-program>> [ delete-gl-program ] when* ]
193         [ texture-sphere-program>> [ delete-gl-program ] when* ]
194         [ plane-program>> [ delete-gl-program ] when* ]
195     } cleave ;
196
197 M: spheres-world pref-dim* ( gadget -- dim )
198     drop { 640 480 } ;
199
200 :: (draw-sphere) ( program center radius -- )
201     program "center" glGetAttribLocation center first3 glVertexAttrib3f
202     program "radius" glGetAttribLocation radius glVertexAttrib1f
203     { -1.0 -1.0 } { 1.0 1.0 } rect-vertices ;
204     
205 :: (draw-colored-sphere) ( program center radius surfacecolor -- )
206     program "surface_color" glGetAttribLocation surfacecolor first4 glVertexAttrib4f
207     program center radius (draw-sphere) ;
208
209 : sphere-scene ( gadget -- )
210     GL_DEPTH_BUFFER_BIT GL_COLOR_BUFFER_BIT bitor glClear
211     [
212         solid-sphere-program>> [
213             {
214                 [ "light_position" glGetUniformLocation 0.0 0.0 100.0 glUniform3f ]
215                 [ {  7.0  0.0  0.0 } 1.0 { 1.0 0.0 0.0 1.0 } (draw-colored-sphere) ]
216                 [ { -7.0  0.0  0.0 } 1.0 { 0.0 1.0 0.0 1.0 } (draw-colored-sphere) ]
217                 [ {  0.0  0.0  7.0 } 1.0 { 0.0 0.0 1.0 1.0 } (draw-colored-sphere) ]
218                 [ {  0.0  0.0 -7.0 } 1.0 { 1.0 1.0 0.0 1.0 } (draw-colored-sphere) ]
219                 [ {  0.0  7.0  0.0 } 1.0 { 1.0 0.0 1.0 1.0 } (draw-colored-sphere) ]
220                 [ {  0.0 -7.0  0.0 } 1.0 { 0.0 1.0 1.0 1.0 } (draw-colored-sphere) ]
221             } cleave
222         ] with-gl-program
223     ] [
224         plane-program>> [
225             {
226                 [ "checker_size_inv" glGetUniformLocation 0.125 glUniform1f ]
227                 [ "checker_color_1"  glGetUniformLocation 1.0 0.0 0.0 1.0 glUniform4f ]
228                 [ "checker_color_2"  glGetUniformLocation 1.0 1.0 1.0 1.0 glUniform4f ]
229             } cleave
230             GL_QUADS [
231                 -1000.0 -30.0  1000.0 glVertex3f
232                 -1000.0 -30.0 -1000.0 glVertex3f
233                  1000.0 -30.0 -1000.0 glVertex3f
234                  1000.0 -30.0  1000.0 glVertex3f
235             ] do-state
236         ] with-gl-program
237     ] bi ;
238
239 : reflection-frustum ( gadget -- -x x -y y near far )
240     [ near-plane ] [ far-plane ] bi
241     [ drop dup [ -+ ] bi@ ] 2keep ;
242
243 : (reflection-face) ( gadget face -- )
244     swap reflection-texture>> [
245         GL_FRAMEBUFFER_EXT
246         GL_COLOR_ATTACHMENT0_EXT
247     ] 2dip 0 glFramebufferTexture2DEXT
248     check-framebuffer ;
249
250 : (draw-reflection-texture) ( gadget -- )
251     dup reflection-framebuffer>> [ {
252         [ drop 0 0 (reflection-dim) glViewport ]
253         [
254             GL_PROJECTION glMatrixMode
255             glPushMatrix glLoadIdentity
256             reflection-frustum glFrustum
257             GL_MODELVIEW glMatrixMode
258             glLoadIdentity
259             180.0 0.0 0.0 1.0 glRotatef
260         ]
261         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z (reflection-face) ]
262         [ sphere-scene ]
263         [ GL_TEXTURE_CUBE_MAP_POSITIVE_X (reflection-face)
264           90.0 0.0 1.0 0.0 glRotatef ]
265         [ sphere-scene ]
266         [ GL_TEXTURE_CUBE_MAP_POSITIVE_Z (reflection-face)
267           90.0 0.0 1.0 0.0 glRotatef glPushMatrix ]
268         [ sphere-scene ]
269         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_X (reflection-face)
270           90.0 0.0 1.0 0.0 glRotatef ]
271         [ sphere-scene ]
272         [ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y (reflection-face)
273           glPopMatrix glPushMatrix -90.0 1.0 0.0 0.0 glRotatef ]
274         [ sphere-scene ]
275         [ GL_TEXTURE_CUBE_MAP_POSITIVE_Y (reflection-face)
276           glPopMatrix 90.0 1.0 0.0 0.0 glRotatef ]
277         [ sphere-scene ]
278         [
279             [ 0 0 ] dip dim>> first2 glViewport
280             GL_PROJECTION glMatrixMode
281             glPopMatrix
282         ]
283     } cleave ] with-framebuffer ;
284
285 M: spheres-world draw-world*
286     GL_DEPTH_TEST glEnable
287     GL_SCISSOR_TEST glDisable
288     0.15 0.15 1.0 1.0 glClearColor {
289         [ (draw-reflection-texture) ]
290         [ demo-world-set-matrix ]
291         [ sphere-scene ]
292         [ reflection-texture>> GL_TEXTURE_CUBE_MAP GL_TEXTURE0 bind-texture-unit ]
293         [
294             texture-sphere-program>> [
295                 [ "surface_texture" glGetUniformLocation 0 glUniform1i ]
296                 [ { 0.0 0.0 0.0 } 4.0 (draw-sphere) ]
297                 bi
298             ] with-gl-program
299         ]
300     } cleave ;
301
302 : spheres-window ( -- )
303     [
304         f T{ world-attributes
305             { world-class spheres-world }
306             { title "Spheres" }
307             { pixel-format-attributes {
308                 windowed
309                 double-buffered
310                 T{ depth-bits { value 16 } }
311             } }
312         } open-window
313     ] with-ui ;
314
315 MAIN: spheres-window